Daily updates from Odoo
Tuesday, July 7, 2026
194 changes
11 changes
Enhancements to existing features
The timesheet assistant now gives clearer guidance when setup issues prevent activity tracking, including distinguishing connection problems from CORS configuration issues and warning when the browser extension is missing or inactive. It also improves suggestion quality by showing real record names, preserving deleted Odoo events properly, and selecting more relevant projects for calendar-based timesheets.
Original PR description
Forward-Port-Of: odoo/enterprise#121939 Forward-Port-Of: odoo/enterprise#115859
Resolved issues and error corrections
Users can now audit values in the Balance Sheet when it is grouped by analytic account without hitting an error. This improves reliability for accounting teams reviewing report details and investigating balances.
Original PR description
Currently an error occurs when user tries to audit a cell when Balance Sheet is grouped by an analytic acccount. Steps to replicate: - Install accountant with demo data and turn on Analytic…
Currently an error occurs when user tries to audit a cell when Balance Sheet is grouped by an analytic acccount.
Steps to replicate:
- Install accountant with demo data and turn on Analytic Accounting.
- Open Balance Sheet Report > Group By an Analytic Account > Click on Any Value under an Analytic Account Column.
Error:
```
File '/home/odoo/src/enterprise/saas-19.3/account_reports/models/account_report.py', line 2876, in dispatch_report_action
return report_method(model, *args)
File '/home/odoo/src/enterprise/saas-19.3/account_reports/models/balance_sheet.py', line 28, in action_audit_cell
action['context'].update({
AttributeError: 'str' object has no attribute 'update'
```
Cause:
- When clicking on a report cell, `dispatch_report_action()` calls `action_audit_cell()` of the corresponding report (Balance Sheet in this case) which in turn calls `action_audit_cell()` of `account.analytic.report`.
- When the flow reaches [1], the window action for analytic items is fetched, where its [context] is returned as a string instead of a dictionary.
- This action is then received [here] with `context` as a string, and attempting to update it results in an error.
Solution:
- Converted the string to dict using `literal_eval()`.
[1]: https://github.com/odoo/enterprise/blob/a26981667361839ad38f45da5a6f23ae8e6478f1/account_reports/models/account_analytic_report.py#L208
[context]: https://github.com/odoo/odoo/blob/824446b65cbe3850f88f56090f0473f0e94bf4f3/addons/account/views/account_analytic_line_views.xml#L88-L91
[here]: https://github.com/odoo/enterprise/blob/b5f884a49344aa097c20fc128e9d290b97970f1a/account_reports/models/balance_sheet.py#L28
opw-6311673
sentry-7513784149
Forward-Port-Of: odoo/enterprise#120734Fixed an issue where the dialog for adding snippets to a mailing could appear behind the full-screen editor when the AI chatbox was active. This restores normal editing behavior and prevents save or discard actions from becoming blocked.
Original PR description
When an AI chatbox is active, all non-error dialog modals are set to be behind the chatbox through their z-index. This causes an issue where the dialog modal to add new snippets to a mailing is set behind the fullscreen edit window, 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. task-6321624
EC Sales List returns are now generated separately for each company in a tax unit using that company's own VAT number. This prevents multiple entities from being incorrectly combined into one declaration under the tax unit VAT number, improving compliance accuracy.
Original PR description
Issue: The EC Sales List return is currently generated under the tax unit VAT number, consolidating all member entities into a single declaration. Expected: The EC Sales List return must be generated individually per member entity, each under their own VAT number, even when those entities belong to a tax Unit. Fix: Apply tax unit only if report's multi company filter is `tax_units`. Ref: https://github.com/odoo/enterprise/blob/07e8aba8604319747a5925c83576095ce9a63f9e/account_reports/models/account_return.py#L316-L317 task-6069402 Forward-Port-Of: odoo/enterprise#115974
Cancelled UrbanPiper delivery orders are now ignored when calculating active delivery counts. This prevents affected point-of-sale sessions from failing to reopen after a delivery provider cancels an order, helping staff continue service without interruption.
Original PR description
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the…
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the delivery provider. 5. Reopen the running POS session. ### Current behavior When a delivery provider cancels an order, the `delivery_status` is updated to `cancelled`, while the POS order state remains (`draft`, `paid`, or `done`). As a result: * Cancelled deliveries are still included in the active delivery order count. * `_get_urbanpiper_order_count()` attempts to map the `cancelled` status, which is not present in `status_map`, raising a `KeyError`. * The POS UI fails to load, preventing users from reopening the running session. ### Expected behavior Cancelled delivery orders should not be considered active delivery orders and should not be included in the delivery status count, allowing the POS session to open normally. ### Solution Exclude orders with `delivery_status = 'cancelled'` from the active delivery order count computation. This prevents the `KeyError` and ensures cancelled delivery orders are ignored when computing active delivery statistics. [Video reproducing the issue](https://drive.google.com/file/d/1XdiylekWV-q6LTbvhCgbyd_KDKlG2imz/view?usp=sharing) --- **opw-6353861** Forward-Port-Of: odoo/enterprise#122798
Shipment insurance configured on Envia delivery methods is now sent in the format expected by Envia. This helps ensure insured shipments, such as those using Mexican FedEx ground services, correctly generate the related insurance documents.
Original PR description
Issue ----- Insurance set on the delivery method is not correctly being communicated to Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - 10% insurance - Create a MX client - Create a product (with some weight) - Create a SO using the delivery method & confirm - Validate the picking > No insurance pdf is being printed Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#121691 Forward-Port-Of: odoo/enterprise#118966
Audit reports exported to PDF now include images inserted with the file command. This prevents missing visual evidence or supporting materials in generated reports, making exported documents more complete and reliable.
Original PR description
Currently, when a user uses the `/file` command to insert an image into an audit report and exports the report to PDF, the image is omitted from the generated PDF. To improve the support of those blocks, we will pre-process the document and replace the embedded files that correspond to images with standard image elements before PDF generation. This will ensure that images are correctly rendered and displayed within the document's text flow in the exported PDF. Task [link](https://www.odoo.com/odoo/project.task/5115280) task-5115280 Forward-Port-Of: odoo/enterprise#122699 Forward-Port-Of: odoo/enterprise#121673
Payroll work entries now avoid counting the same public holiday twice when attendance-based employees also have worked-time leave from sandwich rules. This helps keep generated payroll hours accurate and prevents inflated work entry totals on affected holidays.
Original PR description
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day.…
Issue: When work entries are generated from Attendances, a worked-time time off created by the Indian sandwich rule can overlap a public holiday and generate duplicate work entries for the same day. Steps to reproduce: - Create an employee with Work Entry Source set to Attendances - Use a flexible working schedule on the employee - Configure a public holiday on a scheduled day with work entry type (Paid time off) - Create a time off type with Count as set to Worked Time - Generate time off for the period so the public holiday entry exists (maybe a day before and a the public holiday and the day after) - Open Payroll > Work Entries (Observe the date of the public holiday will have more than 8h entry) Cause: In `_get_version_work_entries_values()`, calendar leaves are split by `hr_holidays` `time_type` into: - leaves: absences and public holidays - worked_leaves: worked-time time off For attendance-based contracts, both sets were turned into work entries without removing overlap between a public holiday and a worked-time leave on the same period. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L222-L226 For non-flexible calendar: Public holidays and worked-time leaves are both clipped to the static working schedule (e.g. 8h per working day). overlap was kept in both result sets. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L260 For flexible calendar: The one-day intervals are kept as the actual interval (often 00:00-23:59 for a public holiday). The worked-time on that day is schedule-shaped (e.g. 8h). Subtracting intervals on a full-day public holiday left a 16h fragment instead of removing the public holiday entry. https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/hr_work_entry/models/hr_version.py#L242-L249 Solution: We need to make regular leaves take priority over worked-time leaves, compute the real regular leave intervals first, then remove those intervals from the worked-time leave intervals before work entries are created: - for fully flexible employees, subtract regular leaves from worked leaves; - for flexible calendars, keep one-day regular leaves as is and subtract them from worked-time leaves - for non-flexible attendance-based calendars, clip regular leaves on the static schedule, then subtract them from worked-time leaves clipped on the same schedule. This means that when a sandwich worked-time leave overlaps a public holiday, the public holiday consumes that period first. The overlapping part is then removed from `real_worked_leaves`, so no second worked-time entry is generated for the same public holiday period. opw-6237163 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#121940 Forward-Port-Of: odoo/enterprise#119530
Users without payroll access can now open employee working schedules without seeing an error linked to Belgian payroll data. The change prevents restricted payroll-related information from being read when the user does not have the required permissions, improving reliability for HR configuration screens.
Original PR description
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees…
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees → Configuration → Working Schedules. **Actual Result:** A traceback is triggered after opening the record. ```python Failed to read field resource.calendar.l10n_be_reorganisation_measure_ids You are not allowed to access 'BE: Reorganisation Measure.' (l10n.be.reorganisation.measure) records. This operation is allowed for the following groups: - Payroll/Assistant Contact your administrator to request access if necessary. ``` **Issue:-** The traceback is caused by the following commit introduced in v19.2 [here](https://github.com/odoo/enterprise/commit/e1092393ff99e9dad84ea8b9d6066e0bc61d6312) In this commit, a new computed field `l10n_be_reorganisation_measure_ids` was added on `resource.calendar`. The field is computed and store=true when the read function is called, and reads the data from the database at that time; The payroll doesn't have any access rights due to the error **Solution:** To fix this issue, a group access check is added inside the field Ticket:- 6245936 Forward-Port-Of: odoo/enterprise#119518
Stripe expense authorizations are now matched correctly when merchant category codes fall within configured ranges, reducing incorrect authorization errors. Declined Stripe expenses also avoid duplicate refusal messages, keeping expense records clearer for users.
Original PR description
# [FIX] hr_expense_stripe: Fix MCC ranges Context: Since 3e52d875 when receiving an authorization whose MCC fits in a range we would not find it in the search. This is logical yet we return an error before checking properly mcc codes with range included After this commit: This will also check that the authorization MCC exist if we don't directly find the range. We move the "not found" error after that check too The forgotten tests have been added into the overrides opw-6185961 opw-6288399 # [FIX] hr_expense_stripe: Fix double refusal of expenses Context: When an expense is created through a declined stripe authorization, the expense is refused twice, resulting in a duplicated refusal message After this commit: Do not refuse already refused expenses Forward-Port-Of: odoo/enterprise#122923 Forward-Port-Of: odoo/enterprise#121474
The Planning Analysis report no longer crashes when the Field Service planning module is installed. The Priority filter is now placed correctly, keeping the report accessible for users reviewing planning data.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Planning > Reporting > Planning Analysis. Issue: - The view crashes with `UncaughtPromiseError > Error: Attribute "domain"` is missing, and the Planning Analysis report cannot be opened. Cause: - The xpath adding the "Priority" filter anchors on `//filter[@name='unpublished_shifts']`, which is a child of the "Status" filter. As a result, "Priority" is inserted inside "Status", and it requires a `domain` on any filter nested inside another filter. "Priority" has none. Fix: - Anchor the xpath on `//filter[@name='status']` instead. task-6358804
15 changes
Enhancements to existing features
UK VAT returns now prompt users when their company belongs to a tax unit and can automatically switch the report to that tax unit. When filing to HMRC, the system uses the tax unit's VAT number where applicable, reducing filing errors for grouped companies.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#122965 Forward-Port-Of: odoo/enterprise#107253
This update improves the French reporting tools used for fiscal declarations. It helps make local compliance reporting more reliable and easier to maintain for businesses operating in France.
Resolved issues and error corrections
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior year of work. This helps produce more accurate termination-related payments for employees with shorter service periods, with added tests covering special 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
EC Sales List returns are now created separately for each company in a tax unit, using that company's own VAT number. This prevents member companies from being incorrectly combined into one declaration under the tax unit VAT number, improving tax reporting accuracy.
Original PR description
Issue: The EC Sales List return is currently generated under the tax unit VAT number, consolidating all member entities into a single declaration. Expected: The EC Sales List return must be generated individually per member entity, each under their own VAT number, even when those entities belong to a tax Unit. Fix: Apply tax unit only if report's multi company filter is `tax_units`. Ref: https://github.com/odoo/enterprise/blob/07e8aba8604319747a5925c83576095ce9a63f9e/account_reports/models/account_return.py#L316-L317 task-6069402 Forward-Port-Of: odoo/enterprise#115974
Task progress shading in the Gantt view now correctly reflects completed work, such as showing 10 hours out of 20 as 50% instead of almost invisible. This helps field service and project users quickly understand task progress from the schedule view.
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
Field service interventions now require both start and end dates before they can be marked complete, and setting one date makes the other required. Send and publish options are hidden when no date is set, helping teams avoid incomplete scheduling information.
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
Swiss payroll now automatically calculates the 2050 salary rule used in ELM transmission. This helps reduce manual corrections and improves accuracy when preparing Swiss payroll reporting.
Original PR description
task-5166226 Forward-Port-Of: odoo/enterprise#108047 Forward-Port-Of: odoo/enterprise#103453
The project Sales Orders tab now correctly shows standard sales orders instead of rental orders when both are linked to the same project. This prevents confusion for users reviewing project-related sales activity and ensures the embedded view reflects the expected business documents.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Open the "Sales Orders" embedded tab. Issue --- In saas-19.3, is_rental_order became a non-stored computed field. When the "Sales Orders" embedded tab filters on non-rental orders, _search_is_rental_order incorrectly translates the domain and matches rental orders instead of standard Sales Orders. Current Behavior --- The standard Sales Order is excluded and the embedded view displays rental orders. Expected Behavior --- The "Sales Orders" embedded tab displays standard Sales Orders linked to the project. Fix --- In _get_sale_orders_domain, replace the is_rental_order filter with explicit checks on rental_start_date and rental_return_date to avoid the faulty search translation. task-6321803
The scheduled process that checks Mexican electronic invoice status now keeps running when more documents remain after a batch is processed. This prevents invoices from being left pending when the process handles them 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
Fixed an issue where the snippet selection window in the mailing editor could appear behind the fullscreen editor when the AI chat was open. This restores normal editing behavior and prevents save or discard actions from becoming blocked during email campaign creation.
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
Fixed an error that prevented the task Gantt view from loading when grouped by sale order item. This lets teams review planned work by customer order line 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
The timesheet assistant now captures time spent in Odoo applications even when the page cannot be linked to a specific project, task, or ticket. This helps users see a more complete set of work suggestions and fixes cases where valid Odoo pages were previously missed.
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
Point of Sale now shows the fuller product list on medium-sized tablet screens instead of switching too early to the compact layout. This gives staff using small tablets a more spacious and usable product selection view while keeping the compact mode for narrower phones.
Original PR description
Previously, the product list was rendered in "small display" mode for all screen sizes below the medium breakpoint (< 992px). However, some small tablets are able to fully display the product list at the medium breakpoint (≥ 768px and ≤ 991px). After this fix, "small display" mode is only applied when the screen width is below 768px. Task.6251934 Community: https://github.com/odoo/odoo/pull/266704 Forward-Port-Of: odoo/enterprise#120777 Forward-Port-Of: odoo/enterprise#119534
Users can now create purchase approval requests even when a product has vendor pricing records linked to vendors they are not allowed to access. This prevents unnecessary access errors in multi-company setups and keeps RFQ approval workflows running smoothly.
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#120251
Shopfloor users can no longer create new serial numbers for manufacturing components when that option is disabled on the manufacturing operation type. This keeps shopfloor behavior aligned with inventory controls and prevents unintended traceability records.
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#111408
12 changes
Enhancements to existing features
UK VAT returns now guide users to file through the relevant tax unit when their company belongs to one. The system uses the tax unit VAT number for HMRC connections and submissions, reducing filing errors and ensuring reports are sent under the correct entity.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#122965 Forward-Port-Of: odoo/enterprise#107253
Belgian payroll rules were updated with the new employment bonus parameters taking effect on 1 July 2026 and 1 September 2026. This helps ensure payroll calculations remain aligned with upcoming legal requirements and reduces the risk of incorrect payslips.
Original PR description
Update the employment bonus parameters for 1st July 2026 and 1st September 2026. task-6369633
Belgian payroll calculations now include updated employment bonus parameters taking effect on 1 July 2026 and 1 September 2026. This helps ensure payroll remains aligned with the latest Belgian rules for eligible employees.
Original PR description
Update the employment bonus parameters for 1st July 2026 and 1st September 2026. task-6369633
Resolved issues and error corrections
EC Sales List returns are now created separately for each company in a tax unit using that company's own VAT number. This prevents member entities from being incorrectly combined under the tax unit VAT number and supports more accurate compliance reporting.
Original PR description
Issue: The EC Sales List return is currently generated under the tax unit VAT number, consolidating all member entities into a single declaration. Expected: The EC Sales List return must be generated individually per member entity, each under their own VAT number, even when those entities belong to a tax Unit. Fix: Apply tax unit only if report's multi company filter is `tax_units`. Ref: https://github.com/odoo/enterprise/blob/07e8aba8604319747a5925c83576095ce9a63f9e/account_reports/models/account_return.py#L316-L317 task-6069402 Forward-Port-Of: odoo/enterprise#115974
The Hong Kong payroll calculation for payment in lieu of notice now accounts for an employee's actual contract start date instead of assuming a full prior year of service. This helps produce more accurate final payments for employees who have worked less than 12 months, with added tests covering 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
Mobile self-ordering now uses the same printing approach as kiosk mode, so preparation receipts are correctly sent to kitchen or preparation printers. The update avoids a failing connection method for mobile customers and uses websocket printing through the IoT Box instead, improving order handling reliability.
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).
A booking availability issue was fixed so appointment types that allow multiple simultaneous bookings can use their configured capacity correctly. This prevents available slots from being blocked after only one booking when capacity management is not enabled.
Original PR description
Previously, the condition which evaluated availability if a conflicting booking existed returned this: `return resource.shareable if self.manage_capacity else True` After a performance improvement commit, it was rewritten into a filter on valid resources, where this was a part of the condition: `not (self.manage_capacity and resource.shareable)` In the original, if manage_capacity was false, we always returned True and later handled capacity using the max_bookings field on the appointment type. In the updated version, if manage_capacity is False, we filter the resource out and only ever allow one booking at a time, regardless of max_bookings This commit updates the condition to act like before Task-6344438
The task Gantt view now shows timesheet progress at the correct scale. This fixes misleading progress bars where partially completed work appeared almost invisible, helping teams quickly understand task completion in planning views.
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
This fix ensures the scheduled process for Mexican electronic invoice status checks continues running when there are more documents left to process. Businesses using Mexican localization will no longer see invoices left pending simply because the batch limit was reached.
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
The task Gantt view now loads correctly when users group tasks by sale order item. This prevents an error caused by an outdated time-planning field name, restoring visibility into task progress for sales-linked projects.
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
This fixes an issue where the snippet selection dialog in the mailing editor could appear hidden when the AI chatbox was open. Users can now add mailing snippets and continue using save or discard actions without the editor appearing frozen.
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
This fix prevents an error that could appear when opening the Time Off “By Employee” report for employees in the French company setup. It ensures the report works correctly even when an employee has no working hours calendar configured, avoiding a disruption for users reviewing leave information.
Original PR description
A singleton error appears when opening the "By Employee" report under Time Off. Steps to reproduce: 1)Install the l10n_fr_hr_holidays module. 2)Switch to the French company. 3)Open any employee record. 4)Set Working Hours (resource_calendar_id) to empty. 5)Set Hours Per Week. 6)Create a time off request for any past date. 7)Go to Reporting → By Employee. Task:-6043142 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#264585
9 changes
Resolved issues and error corrections
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior 12 months of work. This improves payroll accuracy 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
Adding recurring products through the product catalog now follows the same subscription plan validation as manually adding order lines. This prevents confirmed sales orders from accidentally including recurring products without a required subscription plan, reducing billing setup errors.
Original PR description
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product >…
Steps to reproduce: --------------------------------------- 1. Install Subscription Module 2. Create and Confirm SO with no recurring plan and a non-recurring product 3. Add a recurring product > Save SO > Observe the User Error 4. Now add the same recurring product through Catalog View Observation: --------------------------------------- No User Error raised stating 'You cannot save a sale order with recurring product and no subscription plan.' Issue: --------------------------------------- When you manually add a line and click 'Save', the constraint (`_constraint_subscription_plan`) is triggered and raised `UserError` https://github.com/odoo/enterprise/blob/434d88960abb5e424fdc1106fc93935d328bff78/sale_subscription/models/sale_order.py#L176-L177 When you add a product via the catalog view, it calls `_update_order_line_info` which directly creates/updates order lines, Which do not trigger the python constraint. https://github.com/odoo/odoo/blob/ef9772bba1515bdaf5410c3af5a3e395f562d513/addons/sale/models/sale_order.py#L1926-L1933 Solution: --------------------------------------- Two private helpers are introduced: * `_is_exempt_from_subscription_plan_check`: single source of truth for all exempt states (draft, cancelled, upsell, and legacy upgrade orders). * `_check_recurring_plan_mismatch`: raises a `UserError` when the order has or will have a recurring product but no subscription plan, reusing the exemption helper so both call sites stay in sync. `_constraint_subscription_plan` is refactored to delegate to these helpers, and `_update_order_line_info` is overridden to call `_check_recurring_plan_mismatch` before the catalog update is applied, ensuring consistent validation across both entry points. opw-6194865 Forward-Port-Of: odoo/enterprise#122799 Forward-Port-Of: odoo/enterprise#117879
Task progress in the Gantt view now displays at the correct scale. This makes planned versus completed work visually accurate, so users can quickly understand task progress from the chart.
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
EC Sales List returns are now created separately for each company in a tax unit using that company's own VAT number. This prevents multiple entities from being incorrectly combined into one declaration, improving compliance and reporting accuracy.
Original PR description
Issue: The EC Sales List return is currently generated under the tax unit VAT number, consolidating all member entities into a single declaration. Expected: The EC Sales List return must be generated individually per member entity, each under their own VAT number, even when those entities belong to a tax Unit. Fix: Apply tax unit only if report's multi company filter is `tax_units`. Ref: https://github.com/odoo/enterprise/blob/07e8aba8604319747a5925c83576095ce9a63f9e/account_reports/models/account_return.py#L316-L317 task-6069402 Forward-Port-Of: odoo/enterprise#115974
Fixed invoice status handling for Field Service sales orders that include zero-price items. Free items added during a field service task are now treated as included, while free items already on the original quote still follow the normal invoicing process, preventing orders from staying incorrectly open or being skipped incorrectly.
Original PR description
## [FIX] industry_fsm_sale: fix invoice status for zero price lines ### Issue: Without Anglo-Saxon accounting, the system incorrectly sets the invoice status of all zero price sales order lines…
## [FIX] industry_fsm_sale: fix invoice status for zero price lines
### Issue:
Without Anglo-Saxon accounting, the system incorrectly sets the invoice status of all zero price sales order lines linked to an FSM task to 'no'
This includes pre-existing lines that were already present on the quotation before confirmation. If a zero price line is pre-existing, it should follow the standard flow and be marked as 'to invoice'
Only lines added as materials from the field service task at a zero price should be considered included in the price and marked as 'no'
### Cause:
In `SaleOrderLine._compute_invoice_status`, the system forced `invoice_status = 'no'` for all zero price lines when Anglo-Saxon accounting was disabled
It failed to check if the lines were actually materials added via the FSM task or original quotation lines
### Fix:
A new `material_sale_lines` compute field is added to `project.task` to distinctly isolate and track lines added specifically as materials during the task execution
In `SaleOrderLine._compute_invoice_status`, the logic is updated to ensure that only zero price lines identified as FSM materials are set to 'no' when Anglo-Saxon accounting is disabled
Other pre-existing zero price lines properly remain as 'to invoice'
### Steps to reproduce:
- Install `industry_fsm_sale`
- In Settings > Users & Companies > Companies > Any company, add the field Anglo-Saxon using Studio (In 19.0+)
- Disable Anglo-Saxon on the current company
- Create a product Service (Fixed Price, that create a task in a Field Service Project)
- Create and confirm a Sale Order with the Service and one product with unit price 0
Before the fix, the pre-existing SO line with price 0 is
incorrectly considered as not to invoice ('no')
opw-6169802
------------------------------
## [FIX] industry_fsm_sale: sync sale order invoice status
### Issue:
When a sale order contains FSM material lines with a price of zero and Anglo-Saxon accounting is disabled, the overall sale order invoice status remains stuck on 'to invoice' even after all other invoiceable lines are fully invoiced
### Cause:
The standard `SaleOrder._compute_invoice_status` does not handle FSM business rules regarding zero price material lines that are marked as `invoice_status = 'no'`
Because these lines are never technically invoiced, the global order status fails to transition to 'invoiced'
### Fix:
Override `SaleOrder._compute_invoice_status` to recompute the status of confirmed orders linked to FSM tasks
We use the task's `material_sale_lines` to filter out material components
If all lines on the order are either 'invoiced' or are zero price FSM material lines with Anglo-Saxon disabled, the global sale order status is forced to 'invoiced'
### Steps to reproduce:
- Install `industry_fsm_sale`
- In Settings > Users & Companies > Companies > Any company, add the field Anglo-Saxon using Studio (In 19.0+)
- Disable Anglo-Saxon on the current company
- Create a product Service (Fixed Price, that create a task in a Field Service Project)
- Create and confirm a Sale Order with the Service and one product with unit price 0
- Add a Product from the Task (Use a price 0 product, or set the unit price to 0 on the SO)
- Create the invoice for the Sale Order
Before the fix, the Service and Pre-existing product are invoiced, but in the Other Info Tab of the SO, the status stays on 'To Invoice' instead of 'Fully Invoiced'
opw-6169802
Forward-Port-Of: odoo/enterprise#119238This fix restores support for portal users to archive or unarchive documents when the action is performed through trusted system flows. It prevents legitimate document workflows from being blocked while keeping normal access restrictions in place.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows relied on it and we were lacking a way of supporting it. Backport of #123015 Task-6205627 Forward-Port-Of: odoo/enterprise#123164 Forward-Port-Of: odoo/enterprise#123030
The Mexican electronic invoicing process now correctly schedules another status update when more documents remain to be checked. This helps ensure all CFDI invoices are processed instead of leaving some waiting after a batch run.
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
This fix ensures generated website pages use the correct dynamic snippet filters regardless of the order in which modules were installed. It prevents snippets from showing the wrong content and makes website generation more reliable for customers.
Original PR description
Our default dynamic snippets filter ids are set based on the order that we install our modules. This can cause issues if the user installs their modules in a different order. To fix this, we need to update the data-filter-id value to the correct value of the DB. To be able to do this, we also change the regex replacement to use lxml instead since it's much simpler. Lxml part from 799f83575e162eb683cfaebb4eb602ccc1fbe466. Forward-Port-Of: odoo/enterprise#122671
The task Gantt view now loads correctly when users group tasks by sales order item. This prevents an error caused by an outdated hours field and restores progress information in that view.
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#122712 Forward-Port-Of: odoo/enterprise#122297
11 changes
Resolved issues and error corrections
The Twitter social integration now disables the reply option when the account is not permitted to respond to a tweet. This helps prevent failed or inappropriate replies and keeps automated responses aligned with Twitter's rules.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#112161
Fixed an issue where barcode delivery orders could ignore the owner of consigned stock for products without lot tracking. This prevents incorrect stock records from being created and helps ensure deliveries use the right available inventory.
Original PR description
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations >…
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations > Delivery Orders > New - Scan your product and validate #### > The owner was not set on the stock move line so that a new quant was created and updated in stock rather than using the available unit. ### Cause of the issue: The mechanism of prefilling an owner or a package in the barcode app is currently gate-kept behind the existence of a lot name: https://github.com/odoo/enterprise/blob/0be4f71de3420fb9b72fd4e70d48c6cbbbc0ecb4/stock_barcode/static/src/models/barcode_model.js#L1382-L1407 However, the option also make sense for none tracked products. ### Note: Performing the flow form the backend and adding quantity will generate the move line by setting the owner if possible since the quantity of a move is set via the back end, move lines are generated by looking at the existing quant data's: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2364 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2328-L2330 Setting the same owner on the new move line as on the quant we are going to reserve: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2337 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L1715 Additional subtelties appearing when prefilling for non tracked product: 1. Currently the available quantity is not taken into account to determine if the the value provided to the prefilled is actually relevant, in particular if there is a quant with an available quantity of 0, it will be used as a valid value to prefill and it will parasit the prefill that could be done by other quants. 2. The location source used to determine the quants taken into account is not set on the first scan since the scan is performed without any existing line: https://github.com/odoo/enterprise/blob/4f0d25f9fe4ca8ff1b0ecd7900899a2a246ba888/stock_barcode/static/src/models/barcode_model.js#L1387 > This was not problematic with respect to tracked product since the product needs to be scanned prior to the lot, hence there is always a current line when the the lot is scanned. opw-6050657 Forward-Port-Of: odoo/enterprise#122998 Forward-Port-Of: odoo/enterprise#115021
The Turkish Central Bank currency rate provider now uses the official selling rate instead of averaging buying and selling rates. This improves accuracy for accounting and import valuations and better aligns with Turkish customs requirements.
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
This fixes an error that could stop Australian payroll users from computing a payslip after an employee's Income Stream Type was changed. Existing payslips now refresh that payroll detail before calculation, preventing the crash and helping payroll processing continue smoothly.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#120143
DHL deliveries made from a company other than the main company now correctly receive a commercial invoice number. This prevents DHL validation errors for international dutiable shipments and helps users complete deliveries without manual intervention.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#122787 Forward-Port-Of: odoo/enterprise#118379
Restaurant orders handled through Urban Piper are now fetched more efficiently. This reduces repeated server calls during order retrieval, helping the point of sale feel faster and more reliable for staff.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#122907 Forward-Port-Of: odoo/enterprise#120001
Vendor bills imported from Chilean electronic invoices now use the amount in the invoice currency instead of incorrectly using the Chilean peso amount. This prevents overstated or understated bills when companies exchange invoices in currencies such as UF.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#119664
The scheduled process that checks Mexican electronic invoice status with the SAT now correctly continues when more invoices remain in the queue. This prevents invoices from being left unprocessed when the job handles them 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
The task Gantt view now loads correctly when tasks are grouped by Sale Order Item. This prevents an error caused by an outdated hours field name, helping teams review planned work 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#122712 Forward-Port-Of: odoo/enterprise#122297
The timesheet grid now uses each employee's own working schedule to mark public holidays, weekends, and approved time off as unavailable. This helps employees see accurate availability in Timesheets, matching what they expect from the Time Off app.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#95458
This fix restores support for portal users to archive or unarchive documents in cases where the system explicitly grants elevated permission. It preserves tighter access controls while allowing business workflows that depend on portal document status changes to keep working.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows relied on it and we were lacking a way of supporting it. Backport of #123015 Task-6205627 Forward-Port-Of: odoo/enterprise#123030
11 changes
Resolved issues and error corrections
The Turkish Central Bank exchange rate provider now uses the official selling rate instead of averaging buying and selling rates. This improves accuracy for accounting and import valuation, helping align currency calculations with Turkish customs requirements.
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
Australian payroll payslips now refresh an employee's income stream information before calculation. This prevents errors when recomputing an existing payslip after the employee's income stream type has been changed, helping payroll processing continue smoothly.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310 Forward-Port-Of: odoo/enterprise#120143
Vendor bills imported from Chilean electronic invoices now use the correct amount when the invoice is in a currency other than Chilean pesos. This prevents incorrect bill totals and reduces manual correction work for companies handling multi-currency Chilean transactions.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#119664
The Twitter integration now disables the reply option when Twitter rules do not allow a response, such as when the account is not mentioned or the post does not quote one of its tweets. This helps prevent failed or inappropriate automated replies and keeps social media interactions compliant with platform limits.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#112161
Fixed an issue that caused Belgian CODA bank statement imports to crash when files included type 4 blocks. This ensures affected bank statements can be imported normally, reducing disruption for accounting users.
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
The Point of Sale integration for UrbanPiper now gathers all relevant orders in one request instead of making extra sequential calls. This reduces waiting time when fetching orders and helps the POS feel more responsive during order updates.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#122907 Forward-Port-Of: odoo/enterprise#120001
Corrects the Czech VIES XML export so it matches official filing requirements. The report now excludes email data, includes the taxpayer city, and adds required representative name fields for individual companies, reducing validation errors during submission.
Original PR description
**PROBLEM** For VIES report, the xml should not contains the email. The city of the tax payer is missing, and while it's not strictly require, it can modify the tax regime of the payer, so we need to include it in the xml. There is missing fields in the case the company is an individual (zast_jmeno, zast_prijmeni). **STEP TO REPRODUCE** 1. Create an invoice to a EU partner, don't forget to set the transaction code on the invoice line (unhide the field). 2. Go to the VIES reports, and generate the xml. 3. Upload it to https://mojedane.gov.cz/pmd/epo to validate and see the errors. documentation: https://mojedane.gov.cz/dpr/adis/idpr_pub/epo2_info/popis_struktury_detail.faces?zkratka=DPHSHV opw-6190983 Forward-Port-Of: odoo/enterprise#122145 Forward-Port-Of: odoo/enterprise#117698
This fix restores support for approved portal user flows that need to archive or unarchive documents when the system grants elevated permissions. It helps prevent document workflows from being blocked after the earlier access restriction change.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows relied on it and we were lacking a way of supporting it. Backport of #123015 Task-6205627 Forward-Port-Of: odoo/enterprise#123030
The scheduled update for Mexican electronic invoice status now correctly continues when more invoices are waiting than the configured batch size. This prevents invoices from being left unprocessed after a scheduled run, improving reliability for Mexican compliance workflows.
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
The task Gantt view now loads correctly when tasks are grouped by sale order item. This prevents an error caused by an outdated field name and restores progress information for project and timesheet planning.
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#122712 Forward-Port-Of: odoo/enterprise#122297
The timesheet grid now marks public holidays, weekends, and approved personal time off based on the employee's own working schedule instead of only the company default. This helps employees and managers see accurate unavailable days when entering or reviewing timesheets, including schedule changes tied to contracts.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#95458
1 change
Resolved issues and error corrections
This fixes an error that prevented users from opening the task Gantt view when grouping tasks by sale order item. The progress calculation now uses the current task hours field, restoring the view and avoiding disruption for project and sales teams.
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#122297
11 changes
New functionality added to Odoo
Malaysia companies can now use Balance Sheet and Profit & Loss report templates aligned with MPERS standards. This helps businesses produce locally compliant financial statements more easily and consistently in Odoo.
Original PR description
Add Balance Sheet and Profit & Loss reports according to MPERS standards. Community PR: https://github.com/odoo/odoo/pull/271714 task-6159106
Enhancements to existing features
Field service users can now see product availability forecasts and expected arrival timing directly in the stock moves list. This saves time by reducing the need to open each record individually when checking supplementary products for planned sales orders.
Original PR description
Previously, when a sales order for a field service product was planned, adding supplementary products only displayed the basic delivery status in the stock moves list view. To view the replenishment forecast or expected arrival date, users had to navigate into the form view. This commit exposes the `forecast_widget` in the list view. Users can now check product availability and arrival timelines at a glance without opening individual records. task-5929015
Project task users can now dismiss time off warning banners once they have been seen or addressed. Dismissed employees are skipped in future time off checks, reducing unnecessary processing and improving performance on tasks with multiple assignees.
Original PR description
Previously, leave warnings were always computed and displayed for all assigned employees, even if the warning was already known or addressed. For tasks with multiple assignees, this led to unnecessary processing. - Add a dismissal mechanism to the leave warning banner on the task form view. - Exclude dismissed users from the time-off calculation pool to avoid redundant fetching and performance degradation. task-5025297
The preparation display used by kitchen and order teams has been refreshed with a cleaner layout and improved visual styling. A new dark mode makes the screen easier to use in low-light environments and gives restaurants more flexibility for their setup.
Original PR description
*: pos_restaurant_preparation_display, pos_self_order_preparation_display, pos_urban_piper In this commit: ----------------------- - Implemented dark mode for the kitchen display. - Updated styling and layout for improved visuals. Task: 6112459 | Brfore | |--------| | <img width="1919" height="896" alt="image" src="https://github.com/user-attachments/assets/082924e6-f442-429f-afb0-6b5c16b7d761" /> | AFTER | Light | Dark | |--------|--------| | <img width="1919" height="898" alt="image" src="https://github.com/user-attachments/assets/225ce5c1-fee2-4ea7-ac80-5ee9c9232d1b" /> | <img width="1920" height="895" alt="image" src="https://github.com/user-attachments/assets/bee6c761-49ea-49b0-b20e-bd7d96904e6d" /> |
AI chats now behave more like standard Discuss conversations, with message search, editable conversation titles, and a visible favorite button in the header. Tools and Skills setup options were moved under Configuration so administrators can find setup-related settings in a more intuitive place.
Original PR description
AI chats were missing several behaviors users expect from any other Discuss conversation: searching within messages, renaming the conversation, and displaying the favorite button in the header (the action was already available but not visible there). The Tools and Skills configuration entries were also moved from the Agent menu to the Configuration menu, as they are setup-time settings rather than something a user interacts with during day-to-day agent use, and grouping them under Configuration is more consistent with where users expect to find them. task-6326376 Related: https://github.com/odoo/odoo/pull/273973
After a user signs a document, the thank you dialog now only suggests documents that are ready for that user to sign. This prevents users from opening or signing documents before their turn, making the signing flow clearer and more reliable.
Original PR description
Before this fix: After signing a document, the thank you dialog would show pending documents regardless of signing order. This allowed users to navigate to and sign documents even when it was not yet their turn. After this fix: The thank you dialog now only shows documents where it is the user's turn to sign, respecting the signing order set on the request. Impact: Improves user experience by ensuring the signing order is respected when navigating to the next document from the thank you dialog. Task ID: 6306061
Subscription product pages now show discount badges only when a plan is truly cheaper than the one-time purchase option or the relevant comparison price. Goods product pages also avoid showing misleading recurring price information, helping customers compare options more clearly before buying.
Original PR description
Before: - When "Accept One-Time Sale" was enabled, plans priced higher than the Buy Once price still showed a discount badge incorrectly. - For goods products, the "per period" price column was shown, which is misleading since goods are not sold on a recurring price basis. After: - When "Accept One-Time Sale" is enabled, each plan is compared against the Buy Once price; only cheaper plans show a discount badge. - For consumable products, discount is calculated against the most expensive delivery option so cheaper plans show the saving correctly. - For non-consumable products, plan prices are normalized to the shortest billing period for a fair comparison across all plans. - The "per period" price column is now shown only for service products. Impact: - Customers always see accurate discount badges. - Goods product pages no longer show a misleading per-period price, reducing confusion for customers during purchase. Taskid- 6230474
Rental orders now update key dates and prices automatically, reducing manual work and the risk of pricing mistakes. The sales form is also cleaner by showing subscription and rental fields only when they are relevant.
Original PR description
Before this change: - A delivery date field was manually editable and used to control the rental delivery date. - Changing the rental start or end date showed an 'Update Rental Prices' button to update rental pricing. - The rental period field was displayed below the delivery date. - The recurring plan field was visible even when no subscription product was present. After this change: - The delivery date field is hidden and automatically computed from rental_start_date. - Rental prices are automatically recomputed when the rental start or end date changes, removing the 'Update Rental Prices' button. - The rental period field is moved before the pricelist field for better UI flow. -The recurring plan field is now hidden when the order does not contain any subscription product. task-6031439 Community PR:https://github.com/odoo/odoo/pull/255832 Upgrade PR:https://github.com/odoo/upgrade/pull/9693
Project document workspaces now update their company when all linked projects belong to the same company. This removes an inconsistency where projects created in different ways could leave shared documents without the right company assignment.
Original PR description
Before this PR --- - Projects created from the kanban quick create have no company at creation time, so their workspace is born without one. Changing the company later from the form view was silently…
Before this PR
---
- Projects created from the kanban quick create have no company at creation
time, so their workspace is born without one. Changing the company later
from the form view was silently ignored for the workspace, causing the
workspace and its documents to remain without a company.
- Projects created from the list view had their company set at creation, so
their workspace already had a company, and changes were correctly propagated.
This inconsistency made the behavior depend on how the project was created.
After this PR
---
- When a project's company changes, all projects linked to the same workspace
are checked:
- If all linked projects are now in the same company, the workspace company
is updated accordingly.
- If linked projects are in different companies and the workspace has no
company, the workspace is left untouched (accessible to all companies).
- If linked projects are in different companies and the workspace already has
a company, an error is raised (existing behavior, unchanged).
- This makes the behavior consistent regardless of how the project was created
(kanban quick create or list view).
task-4988098Salary offers based on an existing employee version can now use a different PDF template. This gives HR teams more flexibility to tailor offer documents without changing the underlying employee version.
Original PR description
When the offer is based on an employee version (template is the version of the employee), allow to modify `sign_template_id`. Task-6094733
Companies can now explicitly choose whether Stripe Issuing for expense cards runs in demo or production mode. This helps teams test cards safely without creating unnecessary fake Stripe accounts in a live setup.
Original PR description
In this PR: - Added a selection field "Mode" for users to explicitly select demo or production mode. - This avoids unnecessary creation of fake Stripe accounts in production. task-5952661
7 changes
Enhancements to existing features
This update adds the new 13.5% Finnish tax rate and its related reporting group to support an upcoming VAT change from 14%. Businesses using Finnish localization can apply and report the new rate correctly when it becomes relevant.
Original PR description
backport of 5324615 As in Finland the tax rate will change from 14 to 13.5 on certain goods and services those taxes and the corresponding tax group were added to the l10n task-6332565
Resolved issues and error corrections
Fixed an issue where scanning a component product barcode on the shopfloor did nothing when that component was tied to a manufacturing operation. Operators can now scan these products as expected, reducing interruptions and manual follow-up during production.
Original PR description
When scanning a product barcode in the shopfloor, it would not simulate a click on the product if the corresponding BoM line was linked to an operation. Steps to reproduce: ------------------- * Create a BoM for product A with a BoM line for product B and link it to any operation. * Create a WO for product A and confirm it * Open the shopfloor with the WO and scan the barcode of product B > Observation: Nothing happens Why the fix: ------------ We simulate the onClick for the product even if the move is not marked manual_consumption. opw-6268665
Knowledge articles with embedded kanban, calendar, or map views now print and export to PDF correctly. This prevents blank PDFs and ensures users can share complete article content as expected.
Original PR description
When a Knowledge article embeds a kanban, calendar or map view and the user prints it or exports it to PDF, the view is missing and the printed page is blank. The Knowledge print stylesheet hides…
When a Knowledge article embeds a kanban, calendar or map view and the user prints it or exports it to PDF, the view is missing and the printed page is blank. The Knowledge print stylesheet hides those embedded views in print mode. The rule was introduced with the print feature under the selector `.o_knowledge_embedded_view > .o_kanban_view`, but `.o_knowledge_embedded_view` is emitted nowhere in the templates or components, so the rule matched nothing and the embedded views were always printed. Commit https://github.com/odoo/enterprise/commit/69612c80ea0aec5ccf2c2857449da03e61273457 rescoped the print rules and retargeted the selector to the real wrapper as `[data-embedded="view"] .o_kanban_view`. That selector matches, so the views are now hidden and the printed article is blank. Remove the rule from `knowledge_print.scss` so embedded views render again in print mode, restoring the behavior that held since the print feature was introduced. Steps to reproduce: 1. Open Knowledge and create a new article. 2. Click Build an Item Kanban, type a name and click Insert. 3. Add an item with Quick add so a card appears in the kanban. 4. Open the article options menu and click Download PDF. => The embedded kanban view is missing and the PDF is blank. Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6299703) opw-6299703
Lazada order imports no longer adjust individual item quantities based on item-level cancellation statuses. This prevents delivered orders from failing to sync when Lazada reports an exceptional item status after delivery.
Original PR description
Lazada stores order statuses at the item level. When an item is canceled, we mirrored this by decreasing the ordered quantity on the sale order line. But if the item was already delivered, decreasing the quantity below the delivered amount is forbidden and raises a `UserError`, which aborts the whole order sync:
```python
File ".../sale_stock/models/sale_order_line.py", line 420, in _update_line_quantity
raise UserError(_('The ordered quantity of a sale order line cannot be decreased below the amount already delivered. [...]'))
```
In practice, item-level statuses only differ from the order status in exceptional cases. Stop syncing statuses at the item level and assume the entire order shares a single status, which avoids the quantity decrease and the resulting traceback.
opw-6267730This fixes Hong Kong payroll calculations for payment in lieu of notice when an employee has not worked a full 12 months. The calculation now uses the contract start date to determine the relevant days and months, helping produce more accurate final payroll amounts and adding tests for special 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
This fixes an error that could occur when changing quantities on confirmed field service sales orders while automated email/message rules are active. The update keeps internal message suppression working while returning the expected system object, preventing interruptions for users managing field service orders.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#119542Task progress shading in the Gantt view now correctly reflects hours worked against allocated hours. This fixes cases where a half-complete task appeared almost empty, helping users quickly understand task status at a glance.
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
8 changes
Enhancements to existing features
French companies without an Enterprise subscription can now complete required identity verification to submit VAT reports, DAS2, and fiscal declarations through Odoo. If verification was already completed, submissions can continue without extra steps; otherwise, users are guided through the KYC process.
Original PR description
When sending a request from odoo to iap, we do a check subscription on all routes. The problem is that user without enterprise cannot send their vat report, das2 or fiscal declaration. For them, we will ask a kyc process. If the KYC has been done already then fine. Otherwise, we ask the user to do it. task-6208829
The Danish localization reports have been updated to match the 2026 minimal reporting requirements. This helps businesses using Danish accounting reports stay aligned with the latest expected balance sheet and profit and loss formats.
Original PR description
This commit adds the updated minimal reports task-5427493
Xendit payments now support PayNow for Singapore, along with SGD and USD currencies. It also adds more accepted card brands, helping businesses offer a wider range of payment options to more customers.
Original PR description
This commit expands Xendit support to include the Singaporean market and additional card brands. The following changes were made: - Added support for the PayNow (SGQR) payment method. - Added SGD and USD to the list of supported currencies. - Added JCB and AMEX to the supported card brands (available for some markets). - Updated the base payment provider data for Xendit to include PayNow. Task-5964309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
The Turkish Central Bank currency rate provider now uses the official selling rate instead of averaging buying and selling rates. This helps produce more accurate accounting valuations and better aligns import valuation with Turkish customs requirements.
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
This update ensures Colombian city postal codes with fewer digits are formatted correctly before being sent to the Envia delivery service. It helps prevent failed delivery quotes or shipments for affected Colombian locations such as Antioquia.
Original PR description
Issue ----- Delivery does not always work from/to some cities in Colombia, like Antioquia. Cause ----- There was an oversight in fix 7654c55 where only 5 digit postal codes taken from the colombian localisation were padded in https://github.com/odoo/enterprise/blob/390acf532e8932fd9b9a708382a5e36cdbb35754/delivery_envia/models/envia_request.py#L726-L727 However, some of the colombian cities listed in `l10n_co_edi/data/res.city.csv` have 4 digit codes (like `SANTA FÉ DE ANTIOQUIA`, code `5042`). https://github.com/odoo/enterprise/blob/7cceddaf086d849b8e2121e1023ef3479397534f/l10n_co_edi/data/res.city.csv#L12 These 4 digit codes have to be right-padded to 5 characters before the left-padding to match the official colombian zip codes. See colombian gov official document (PDF download) where the code is actually `05042`. https://www.dane.gov.co/files/censo2005/provincias/subregiones.pdf ----- Ticket: opw-6248252
When importing Chilean electronic invoices in a currency such as UF, vendor bills now use the invoice's currency amounts instead of mistakenly using Chilean peso values. This prevents incorrect bill totals and improves accuracy for companies handling multi-currency Chilean documents.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#119664
Fixed an issue where expanding a Knowledge sidebar article could show only a favorited child article while hiding its other children. Users can now reliably see the full article hierarchy without needing to reload the page.
Original PR description
The sidebar always loads the user's favorite articles along with the visible ones, so a favorited article is shown as a root of the favorite tree. When that favorite is also a child of a folded…
The sidebar always loads the user's favorite articles along with the visible ones, so a favorited article is shown as a root of the favorite tree. When that favorite is also a child of a folded article, it gets added to its parent's child_ids in the main tree, even though the parent's other children were not fetched. A folded article only gets its favorited children back from get_sidebar_articles, not its whole child set. When the parent is then unfolded, unfold() only read the children from the database when child_ids was empty. The favorited child already filled child_ids, so the call was skipped and the remaining children stayed hidden until the next reload. unfold() now uses a new children_loaded flag instead of the length of child_ids to decide whether to fetch the children. The flag is set once an article's whole child set is loaded: in loadChildren(), and in loadArticles() for the articles that were unfolded, since those come back with all their children. loadChildren() also rebuilds child_ids from the search result so a favorite already loaded is not added twice. The fix lives in the sidebar component because the partial child_ids only exists on the frontend, get_sidebar_articles already returns the right records. Steps to reproduce: 1. Open the Knowledge app 2. Create an article with two child articles 3. Add one of the two children to your favorites with the star icon 4. Open another article that is not under that parent 5. Fold the parent article in the sidebar, then refresh the page 6. Expand the parent article => only the favorited child is shown under the parent, the other child is missing Ticket [link](https://www.odoo.com/odoo/project.task/6186466) opw-6186466
The timesheet grid now marks public holidays, weekends, and approved time off based on the employee's own working schedule instead of always using the company default. This helps employees and managers see accurate unavailable days when entering or reviewing timesheets.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080 Forward-Port-Of: odoo/enterprise#95458
4 changes
Enhancements to existing features
Attachment deletion is now much faster for companies using Chilean electronic invoicing and stock documents. This reduces delays during cleanup operations on large databases, improving system responsiveness without changing user workflows.
Original PR description
## The problem Deleting attachments checks foreign key triggers. Lookups in `account_move` and `stock_picking` tables for `ir_attachment` related fields coming from `l10n_cl_edi` overrides were slow due to missing indexes. ## The solution Added needed indexes to optimize triggers' lookups. ## Benchmark Time benchmark (deleting attachments from a customer database with 224K account moves and 204K stock pickings): |# of rows|Time (Before)|Time (After)| |----------|--------------|-------------| 100 | 29s | 16ms 1000 | 285s | 300ms OPW-6331845
Attachment deletion is now much faster for Chilean electronic invoicing and stock documents. This reduces delays when cleaning up or managing files in databases with large volumes of accounting and inventory records.
Original PR description
## The problem Deleting attachments checks foreign key triggers. Lookups in `account_move` and `stock_picking` tables for `ir_attachment` related fields coming from `l10n_cl_edi` overrides were slow due to missing indexes. ## The solution Added needed indexes to optimize triggers' lookups. ## Benchmark Time benchmark (deleting attachments from a customer database with 224K account moves and 204K stock pickings): |# of rows|Time (Before)|Time (After)| |----------|--------------|-------------| 100 | 29s | 16ms 1000 | 285s | 300ms OPW-6331845
Resolved issues and error corrections
This fix brings improvements from a newer version into Odoo 17 to make the scheduled update of Mexican invoices' SAT status more reliable. Businesses using Mexican e-invoicing should see fewer incorrect or missed status updates when the automated check runs.
Original PR description
Several fixes were applied in version 18.0 to the scheduled action responsible for updating invoices' SAT status. - a6c3465fb86f7af162c90e1adab7bd1da1a1c20d - 1eec6de32c99396ae40587168193dbc44ebae1e3 - a1b130566f6689a0c3c786a98f75c54234467fcc We propose to backport them in version 17.0.
The Peru Profit and Loss report now includes Other Operating Income when calculating gross profit and related totals. This ensures reported profit figures reflect all relevant operating income, improving accuracy for financial review and compliance.
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