Daily updates from Odoo
Wednesday, July 1, 2026
45 changes · saas-19.3
Enhancements to existing features
This change speeds up how Odoo retrieves task activity information used by the /mail/data endpoint. By adding a database index, the system can find the relevant records much faster, reducing wait times and improving overall responsiveness.
Original PR description
`/mail/data` is called a lot. It spends roughly 33% of its time on the query fetching task activities in `_get_activity_groups` https://github.com/odoo/odoo/blob/a52b277a4db5f14516717738ca962e3bb3c7180f/addons/project_todo/models/res_users.py#L27 This commit adds an index to speed up the query. - before ~25ms https://explain.dalibo.com/plan/72b26edce8448b51 - after <1ms https://explain.dalibo.com/plan/c4g6851e5b4hh702 task-6327159 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272712
This update makes Odoo’s logging easier to customize, including support for structured log formats and external logging handlers. It helps teams route, filter, and store logs in ways that better fit their operations, without changing normal logging behavior by default.
Original PR description
Stable friendly backport of #270562 Less elements where moved, cleaned, removed, ... keeping the minimal changes to make it work in stable. Forward-Port-Of: odoo/odoo#273127
This update makes sure the label shown for the reconciliation setting is consistent across accounting models. It improves clarity for users by displaying the same updated wording everywhere, avoiding confusion from mixed old and new labels.
Original PR description
Since this PR https://github.com/odoo/odoo/pull/249536 "Allow Reconcilation" became "Payment Reconciliation" This change in labels didn't take effect in the account.move.line model. This commit fixes this issue by ensuring that the label of is_account_reconcile field matches that of the account.account.reconcile field. task-6306159
Resolved issues and error corrections
This update fixes the Peru Kardex PLE stock report so it now calculates inventory values and opening balances correctly, even when later purchases change average cost. It also keeps special stock movements, like landed costs, visible in the report without requiring extra dependencies.
Original PR description
*Continuing on the work from https://github.com/odoo/enterprise/pull/111526, new PR because we cannot push to it.* Adapt the Kardex PLE 12.1/13.1 reports from the SVL-based approach in 18.0 to the stock.move-based approach required in 19.0. Key changes: - Use traceable IDs (account_move_id/stock_move_id) for CUO field - Back-calculate opening balance cost at report date instead of using current standard_price, which is wrong when post-period purchases have changed the average cost - Filter storable products only (is_storable) matching v17/v18 behavior - Handle negative opening balance quantities correctly - Add bridge module l10n_pe_reports_stock_landed_costs to show landed costs as separate Kardex lines (operation_type=26) without forcing stock_landed_costs as a hard dependency Forward-Port-Of: odoo/enterprise#121855
The restaurant point of sale now only shows the Split action when bill splitting is turned on in the configuration. This avoids confusing staff with an option they cannot use and keeps the Actions menu aligned with the store’s settings.
Original PR description
Previously, the Split action remained available in the restaurant PoS even when bill splitting was disabled in the POS configuration. Steps to reproduce: - Disable the split bill option in the restaurant POS configuration. - Open a restaurant POS session. - Select a table and add multiple products. - Open the Actions menu. - Observe that the Split action is still displayed. This commit ensures that the Split action is only shown when bill splitting is enabled in the PoS configuration. Task-6294276
Internal notes in Point of Sale now keep the original tag colors when a color has been set, instead of forcing every tag to use the same background. This makes colored notes easier to read and helps staff distinguish tags more quickly in light mode.
Original PR description
Before this commit: ===================== The internal note styling applied a custom background color to all tags, overriding the colors provided by TagsList (o_tag_color_*). As a result, colored tags were displayed with the default background in light mode. After this commit: ====================== The custom background color is applied only to default tags, while tags with an explicit color keep their original TagsList styling. Additionally, demo internal notes were updated with color values to showcase the colored tag behavior. Task:6294250 Forward-Port-Of: odoo/odoo#269746
This update fixes an issue where invoices sent to Viettel S-Invoice could fail when the returned ZIP file had a different structure than expected. The system now correctly finds the XML whether it is directly in the ZIP or inside nested ZIP files, preventing errors and improving reliability.
Original PR description
Description of the issue/feature this PR addresses: The actual XML extraction hardcoded the double-zipped case by reading only the first entry of the outer zip (`zip_file.infolist()[0]`), assuming it…
Description of the issue/feature this PR addresses: The actual XML extraction hardcoded the double-zipped case by reading only the first entry of the outer zip (`zip_file.infolist()[0]`), assuming it was always a nested zip containing the XML. This made it fail when: - The XML was directly in the outer zip (single-zipped). - The zip contained multiple files and the first nested zip didn't hold the XML. Current behavior before PR: After sending an Invoice to Viettel S-Invoice, the e-Invoicing platform would return a ZIP containing one XML file. The XML File being double-unzipped, a traceback is raised. Desired behavior after PR is merged: The fix rewrites _recursive_zip_xml_file_data to actually be recursive. Invoices can be sent to Viettel S-Invoice without raising a traceback. opw-[6249929](https://www.odoo.com/odoo/project.task/6249929?debug=1) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272121 Forward-Port-Of: odoo/odoo#268482
Planning reports can now be printed safely even when grouped by fields like Role or Project instead of Employee. This prevents crashes during report generation and ensures multi-day shifts are handled correctly, improving reliability for users who rely on customized planning views.
Original PR description
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or…
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or `AttributeError`. ### Cause: The `action_print_plannings` method hardcoded the assumption that the `group_by` key would always be a `resource.resource` recordset. 1. When the user grouped by other fields, it returned strings, booleans, or empty recordsets, causing crashes when the code blindly called `.id` and `.display_name`. 2. During the sorting phase, mixing `False` (for unassigned empty recordsets) with strings caused a `TypeError`. 3. For multi-day shifts, the method failed to extract the actual resource to calculate the shift splits if the grouping was not explicitly set to `resource_ids`. ### Fix: - Implement safe attribute checks (`hasattr`) when extracting group IDs and display names. - Ensure unassigned empty recordsets properly fall back to the "Undefined" string and empty strings during sorting to prevent TypeErrors. - Universally fallback to extracting the resource directly from the slot (`slot.resource_ids[:1]`) for multi-day time splitting when grouped by non-resource fields. - Add a unit test to ensure stability when grouping by `role_id` with multi-day shifts. Task: 6244057 Forward-Port-Of: odoo/enterprise#118530
This change prevents an error that could occur when the system looked up an IoT device and found more than one match. It makes device access more reliable by ensuring only one device record is used, avoiding interruptions for users relying on IoT features.
Original PR description
Currently, a singleton error occurs while accessing the `type` field on `iot_device`, as the search assigned to `iot_device` returns multiple `iot.device` records. Error: `ValueError: Expected singleton: iot.device(5, 10)` This commit fixes the above issue by adding `limit=1` to the search, ensuring that `iot_device` always contains a single record and preventing the singleton error. Sentry-7579060623 Forward-Port-Of: odoo/enterprise#122219
This update keeps parent POS orders correctly in sync after repeated split-and-pay actions in the Orders tab. It prevents already paid items from remaining on the draft order, which avoids the same items being charged more than once.
Original PR description
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid…
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid in previous splits. Functionally, the cashier can keep splitting and paying the same line again and again because the parent draft order is not updated consistently in that path. Steps to reproduce: ------------------- * Enable POS Restaurant with l10n_de Fiskaly * Create a table order (e.g. 3 meals + 3 drinks) * Open Split Bill, move 1 meal + 1 drink, and pay * From Orders tab, open the remaining parent order and repeat split + pay * Reopen the parent order from Orders tab > Observation: The parent order still contains quantities that were already split/paid, so the same items can be paid multiple times from the Orders tab. Why the fix: ------------ The Fiskaly `syncAllOrders` override diverged from core sync behavior in the split flow: it ignored explicit `options.orders` and did not await transaction creation for inactive transactions. In the split-bill path this could skip or desynchronize parent-order updates, leaving stale quantities on the parent order. The fix restores expected sync semantics by honoring `options.orders` and awaiting transaction creation before deciding sync eligibility. opw-6175880 Forward-Port-Of: odoo/enterprise#117206
This change fixes an issue that could prevent managers from creating a group time off request for multiple employees. If no time-off work type is configured, the system now handles that case safely instead of showing an error.
Original PR description
Currently, an error occurs when a user tries to create a group time off. **Steps to Reproduce:** - Install the `hr_presence` module without demo data. - Go to `Employees` > `Configuration` > `Working…
Currently, an error occurs when a user tries to create a group time off. **Steps to Reproduce:** - Install the `hr_presence` module without demo data. - Go to `Employees` > `Configuration` > `Working Times` > `Time Types` and delete all records. - Make sure there are at least `two employee` records. - Go to `Employees` and switch to the `list view`. - Select `both employees` > click `Presence Control` > click `Create a Time Off`. **Error1:** `TypeError: unsupported operand types in: hr.work.entry.type() | None` **Error2:** `AttributeError: 'NoneType' object has no attribute 'ids'` When a user creates a group time off record and the wizard is opened, it computes the valid work entry types. If no work entry type exists, accessing the `True` key (`requires_allocation`) from the empty dictionary returns None [1]. Later, when performing a union (|) between an empty work entry type recordset and None, it raises the first error [2]. Additionally, accessing ids on None raises the error [3]. This commit ensures that when no work entry type exists, accessing key(requires_allocation) from an empty dictionary returns an empty work entry type record instead of None. [1]- https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L144-L145 [2]- https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L146 [3]: https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L148 sentry-7552717400 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue where rental and non-rental quotations linked to an opportunity could disappear from the Quotation list. This ensures users can correctly review all expected quotations from the opportunity, improving visibility and day-to-day sales follow-up.
Original PR description
Steps to reproduce: 1. Install sale_crm and sale_renting_crm 2. Create an opportunity 3. On this opportunity, create two quotations from the `New quotation` button 4. From the opportunity's form…
Steps to reproduce:
1. Install sale_crm and sale_renting_crm
2. Create an opportunity
3. On this opportunity, create two quotations from the `New quotation` button
4. From the opportunity's form view, click on the `Quotation` smart button
Issue:
- The quotations are not visible in the list view
Why?
- In module `sale_renting_crm`, we override the domain to exclude rental quotations.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting_crm/models/crm_lead.py#L33-L36 But from the saas-19.3 `is_rental_order` field is no longer stored in the DB, It is computed now and filtered through `_search_is_rental_order`.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting/models/sale_order.py#L223-L227 The search method did not properly handle the Boolean search shape used by the ORM, so the quotations were incorrectly filtered out. In our case, we gave the domain `("is_rental_order", "=", False)` but the operator is translated to `not in` and value to `Orderedset([True])` by the domain optimiser
Solution:
- Update `_search_is_rental_order()` to handle the ORM-normalized boolean search correctly for rental and non-rental quotations.
opw-6304696This update refreshes the spreadsheet component and fixes an issue that could prevent certain accounting data from being handled correctly. It improves how spreadsheet pivot tables interpret data, which helps reports display more reliably for affected users.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/040ae04f23 [REL] 19.3.10 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/040ae04f23 [REL] 19.3.10 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/37a0a7031f [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/3412fa57da [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
This fix prevents a crash when translating report XML in Studio on databases where English is not installed. It makes the translation flow more reliable for users working in other base languages.
Original PR description
Init a db with a language different from en_US install other languages, except en_US Try to translate via studio a report's XML This gives a crash, because the baseLang is not installed After this commit, there is no crash. opw-6239938 Forward-Port-Of: odoo/enterprise#122026
When a sign template is duplicated, its roles are now copied as well instead of being shared with the original template. This prevents changes made to one template from unexpectedly affecting another, keeping each template independent.
Original PR description
When duplicating a sign template, its sign items were copied but their `responsible_id` was kept as a reference to the same `sign.item.role` records. As a result, editing a role on one template (e.g. assigning a partner through `assign_to`) leaked to the other template sharing it. Copy the role when copying a sign item so each template owns its own roles. task-6288951 Forward-Port-Of: odoo/enterprise#121411 Forward-Port-Of: odoo/enterprise#119864
This update fixes an internal testing issue in the Point of Sale and Loyalty areas by making temporary test changes automatically clean themselves up. It helps keep the system’s code checks reliable and prevents false test failures during development and validation.
Original PR description
Avoid polluting the Odoo model registry and failing `test_lint_override_signature` by using `patch.object` instead of manual assignment. This ensures the injected method is properly torn down after the test block, keeping the registry clean and bypassing static analysis failure as the patched method is only used for tests. runbot-939298 Forward-Port-Of: odoo/odoo#273096
This change prevents errors when users work with products that do not yet have a generated variant. It hides or blocks inventory-related actions that depend on a variant, avoiding broken forecast, replenish, and on-hand quantity behavior.
Original PR description
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1-…
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1- Create a dynamic attribute with values. 2- Create a product and without saving: - Enable track inventory. - Add the dynamic attributes and values. 3- Save the product. 4- Click on forecasted quantity smart button: - There is a traceback. 5- Click on Replenish: - Unexpected behavior. 6- Click on `Product On Hand Quantity`: - No product will be shown if you try to add quantity. Cause: --- This is caused because there is no variant created. In the steps, if you save the template once before adding dynamic attributes, a single variant will be created which allows it to work without issue. Fix: --- we can fix the TB by hiding the forecasted qty smart button, when there is no variant. However, there will be still issue with `Replenish` flow, which requires a variant. We could do the prevent the issue by ensuring there is at least one variant. opw-6260253 Forward-Port-Of: odoo/odoo#272943 Forward-Port-Of: odoo/odoo#268879
This update adjusts an automated test so it works whether the accounting app is installed or not. It matters because the payment status can now be handled correctly in both setups, preventing false test failures during builds.
Original PR description
If accountant is installed, payment state of unreconciled payment switch from 'paid' to 'in_payment'. Not having accountant break the test. runbot-939445 Forward-Port-Of: odoo/enterprise#121113
This update fixes a test issue in the POS Urban Piper module by making sure temporary test changes are removed properly after the test runs. It helps keep the system’s internal checks stable and prevents unnecessary test failures.
Original PR description
Avoid polluting the Odoo model registry and failing `test_lint_override_signature` by using `patch.object` instead of manual assignment. This ensures the injected method is properly torn down after the test block, keeping the registry clean and bypassing static analysis failure as the patched method is only used for tests. runbot-939298 Forward-Port-Of: odoo/enterprise#122283
This change fixes an unreliable automated test in the messaging app. It ensures the retry scenario is checked in a more realistic way, so test results are consistent and do not hide real issues.
Original PR description
The "Retry loading more messages on failed load more messages" test drove load-more by scrolling (real IntersectionObserver) and failed the fetch synchronously, then clicked retry immediately. The observer could fire the older-fetch twice and leave a second fetch in flight at the retry click, which then no-op'd (fetchMoreMessages bails while a fetch is loading), leaving 30 messages instead of 60. This is a test-timing artifact: a real user retries long after any fetch has settled. Fail the load-more through a Deferred rejected only once the fetch is in flight, like jump_to_present.test.js. While it is pending, duplicate observer fires no-op, so no orphan fetch can race the retry. https://runbot.odoo.com/odoo/error/242113 Forward-Port-Of: odoo/odoo#272942 Forward-Port-Of: odoo/odoo#272430
This update makes the website rental tests more reliable and better aligned with real website behavior. It ensures payment setup only happens when the demo payment data is available, allows weekend rentals in tests, and searches for the intended product on the shop page so the automated flow does not break unexpectedly.
Original PR description
## [FIX] website_sale_renting_planning: prepare payment if demo is installed Before this commit, the demo `payment.provider` for the tests was being created in `setUpClass` this caused an issue…
## [FIX] website_sale_renting_planning: prepare payment if demo is installed Before this commit, the demo `payment.provider` for the tests was being created in `setUpClass` this caused an issue because `payment_demo` is not a dependency of this module, therefore it may not be installed while these tests are running and cause the tests to error at setup. After this commit, the `payment.provider` creation was moved into the tests after the check for `payment_demo` installation, ensuring that `payment_demo` would exist when a `payment.provider` is prepared. https://runbot.odoo.com/odoo/runbot.build.error/940273 ## [FIX] website_sale_renting_planning: unforbid weekend in tests Before this commit, the company had `renting_forbidden_sat` and `renting_forbidden_sun` enabled which made it not possible to rent products from website if the rental date included a saturday or sunday. This commit fixes that but setting `renting_forbidden_sat` and `renting_forbidden_sun` to False and allowing rental on all days of the week. https://runbot.odoo.com/odoo/runbot.build.error/940312 ## [FIX] website_sale_renting_planning: search for product in shop page Before this commit, the website `/shop` page would display all published products in the db, this could cause the `website_sale_renting_planning_buy_product` tour to fail if the setup product is not in the first page. After this commit, the `/shop` page is now access with a search on the product to ensure there won't be other products in the first page. https://runbot.odoo.com/odoo/runbot.build.error/940275 Forward-Port-Of: odoo/enterprise#121342
This update ensures the UAE payroll rules stay properly synchronized when payroll data is refreshed. It helps prevent incorrect salary rule behavior and keeps payroll calculations consistent.
Original PR description
. Add hr_rule_parameter_data & hr_salary_rule_data to _get_data_files_to_update() task-6347544
This update corrects issues in the Egypt payroll payment form so exported ETA forms open properly. It also ensures missing-field warnings refresh correctly when the required employee data is completed, reducing confusion during payroll processing.
Original PR description
Issue 1: Steps to Reproduce: -> Create Payslip for Employee -> Once payslip is validated, Click Pay, and for Mode Choose ETA Form 2 -> Download and open the File it throws Formatting error Cause: The Excel workbook was base64-encoded before being written to the binary field, which expects raw bytes. Fix: Save raw binary data directly and update the test case to load it using `io.BytesIO` on binary field content Issue 2: Steps to Reproduce: -> Create a payslip for an employee missing (like EG Social Insurance Number) -> A warning is raised that field is missing. -> Even if the field is filled, the warning does not disappear. Cause: There is no compute dependency to recompute warnings when value changed. Fix: Added dependency in `_issues_dependencies` so it recomputes when value changes. task-**6292194**
We adjusted an automated test so it always runs from a fixed mid-week date instead of using the current day. This prevents the test from failing on weekends and makes the avatar card tour results reliable for everyone.
Original PR description
The avatar card tours create a time off relative to "today" and assert the "Back on" out-of-office indicator. When the test runs on a Friday or Saturday, today+1 is a weekend, so the leave's date_to lands on that weekend day's 00:00 and the "currently on leave" window closes at midnight. Once the run crosses that boundary the leave is no longer active, the indicator disappears and the tour fails at the "Back on" step, deterministically on that weekday. Freeze setUpClass to a fixed mid-week day so the time off always ends on a working day. https://runbot.odoo.com/odoo/error/242512 Forward-Port-Of: odoo/odoo#273073
This change fixes an error that could appear when opening sales order lines in a wizard, preventing the page from loading correctly. It restores the missing product reference needed by the unit-of-measure field so the sales order line list works as expected.
Original PR description
- Description of the issue/feature this PR addresses: - The mandatory product_id field required by the many2one_uom widget was omitted from the list view, causing the issue. - The issue occurred when…
- Description of the issue/feature this PR addresses:
- The mandatory product_id field required by the many2one_uom widget was omitted from the list view, causing the issue.
- The issue occurred when the customized 'Extend Order' button was clicked, opening the wizard with all sales order lines loaded into its one2many field.
- Error message: UncaughtPromiseError > OwlError
Uncaught Promise > An error occured in the owl lifecycle (see this Error's "cause" property)
Occured on apollohomecare-migration-v19-33341368.dev.odoo.com on 2026-06-26 10:18:38 GMT
OwlError: An error occured in the owl lifecycle (see this Error's "cause" property)
Error: An error occured in the owl lifecycle (see this Error's "cause" property)
Caused by: Error: The widget 'Many2OneUomField' (field 'product_uom_id') needs a 'product.product' or 'product.template' field. 'product_id' is used but is related to 'undefined' model.
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#272417This change prevents an error that could occur on invoices when a payment term is selected and the currency is cleared. If the currency is temporarily missing, the system now uses a safe fallback so users can continue working without encountering a crash.
Original PR description
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new…
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new invoice - Add a line - Add a customer - Save - Select payment term as `30% Now, Balance 60 Days` - Remove the currency. Error: ``` ValueError: Expected singleton: res.currency() ``` Cause: - This error only occurs when the selected payment term contains at least two due term lines [1]. - When the selected payment term has atleast two lines the check [1] assigns `on_balance_line` as false and the `else` block is evaluated where currency being an empty recordset (as the user removed it) causes the error from [line] when trying to perform `round()` on an empty res.currency recordset. Solution: - As the currency is a required field, user will not be able to save the record until a currency is assigned. - Used journal's currency or company's currency as a fallback when computing payment terms if the current currency is empty. [1]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L229 [line]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L240 sentry-7569922293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272073
This change removes an inefficient repeated lookup when determining a partner’s main user. It improves performance significantly for large lists of records, which means faster operations during activities like auto-subscribing users to discussion channels.
Original PR description
**Current behavior before PR,** Computing `main_user_id` of a partner involved filtering active users within a loop. To avoid losing the prefetching, we manually forced all partner users to be kept…
**Current behavior before PR,** Computing `main_user_id` of a partner involved filtering active users within a loop. To avoid losing the prefetching, we manually forced all partner users to be kept in the prefetch during each iteration. This caused performance issues as the recordset grew large (e.g., during auto-subscription). **Desired behavior after PR is merged,** All partner users are prefetched and filtered once, removing the need for a repetitive manual prefetch. **Benchmark,** The following observations were recorded when auto-subscribing users to a discuss channel at different scales. The _Before_ and _After_ results represent the max values from three consecutive tests. | Records | Before | After | | :--------| -------: | ---------: | | 3k | ~2.3s | <90ms | | 5k | ~3.8s | <160ms | | 10k | ~7.6s | <300ms | part of task-6116079 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271549
When a new file is uploaded in Documents, its available actions are now shown right away. This removes the need to deselect and reselect the file before continuing, making the workflow smoother and faster for users.
Original PR description
Bug === When uploading a new file in documents, it's selected, but the actions are not visible (we need to unselect - select the record to see the actions). Task-5408471 Forward-Port-Of: odoo/enterprise#122102 Forward-Port-Of: odoo/enterprise#114770
When a PEM certificate file is uploaded, the system now keeps the entire certificate chain instead of only the first certificate. This improves compatibility and ensures certificate-based flows work as expected when intermediate certificates are included.
Original PR description
Previously, only the leaf certificate was parsed when loading PEM-encoded data, ignoring any additional certificates in the chain. This change updates the loading logic to include the full certificate chain, ensuring proper integrity and compatibility with flows that require it. Useful for this PR: odoo/odoo#254906 Task [link](https://www.odoo.com/odoo/project.task/6053921) task-6053921 Forward-Port-Of: odoo/odoo#255100
Selling combo products in Kenyan Point of Sale now works correctly with eTIMS. The system no longer treats the combo header as a separately registered item, so users will not see a blocking warning when only the items inside the combo are registered.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#122179 Forward-Port-Of: odoo/enterprise#119362
This fix prevents payroll calculations from crashing when the expected student wage salary scale cannot be found. Instead of failing, the system now handles the missing value safely so payroll processing can continue normally.
Original PR description
When computing _get_student_min_wage and the specific salary scale is not found, it returns None and then fails in the tuple compression as None is not an interable. task-6318004
This update prevents the Point of Sale from crashing when Adyen sends repeated payment notifications for the same transaction. It ensures duplicate messages are safely ignored so payments continue to complete normally without interrupting the cashier experience.
Original PR description
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers…
The following error is raised in the POS when paying with an Adyen terminal: ``` TypeError: Cannot read properties of undefined (reading 'uuid') at Proxy.handleAdyenStatusResponse ``` Adyen delivers webhook notifications at-least-once, so the ADYEN_LATEST_RESPONSE event can fire several times for a single payment, running handleAdyenStatusResponse concurrently. After the await on get_latest_adyen_status, a previous (duplicate) notification may already have resolved the payment line, so getPendingPaymentLine no longer returns it and the subsequent line.uuid dereference crashes. opw-6237987 patched the same root cause on a single line by adding an optional chaining operator in isPaymentSuccessful, which only moved the crash to the next dereference. Fetch the pending line once at the start of handleAdyenStatusResponse and bail out when it is gone, so every dereference below is safe. The same guard is added to the remaining branches of _adyen_handle_response for consistency with the existing Reject branch. opw-6237987 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271181 Forward-Port-Of: odoo/odoo#269720
Images given a device-style shape will now be cropped to match that shape instead of being forced into a square first. This reduces unnecessary cropping and preserves more of the original image, especially for tall or narrow images.
Original PR description
Scenario: - insert image with ~ 1:2 ratio (height bigger than width) - set shape "iPhone `#2`" to that image Result: the image should fit without much cropping the 0.46:1 aspect ratio of the shape, but it is cropped 1:1 before being applied to it. Cause: when the image has a set aspect ratio, we are always cropping it to 1:1 aspect ratio in postProcessCroppedCanvas but it should be cropped to the shape aspect ratio as it was done in previous version. Fix: go back to what was done in saas-18.3 and apply the shape aspect ratio and not just square (1:1) aspect ratio. opw-5415137 Forward-Port-Of: odoo/odoo#250922
When a business card is scanned, the contact’s city is now captured along with the other details. This makes scanned contact records more complete and reduces the need for manual edits.
Original PR description
Previously, when user scans any business card, every information was fetched except for the city name. After this commit the city field will be properly fetched. task-6332914 Forward-Port-Of: odoo/enterprise#121766
This change fixes an issue where the portal homepage flow could get stuck during testing because the page was not fully ready before the next step ran. It helps ensure the portal experience loads reliably and prevents test timeouts.
Original PR description
Since #256698, the `undeterministicTour_doNotCopy` flag was removed. Without this artificial delay, the `portal_load_homepage` tour executes steps faster than the website frontend JavaScript can finish initializing and binding event handlers to the form. Leaving the tour stuck on a blank text screen after Saving and causing a script timeout. Fix this by ensuring the frontend framework is fully initialized before interacting with the form fields. [Runbot-242298](https://runbot.odoo.com/odoo/runbot.build.error/242298) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue where completed documents signed through eMSigner could be downloaded as the original uploaded file instead of the signed version. This ensures customers now receive the final signed PDF after the signing process finishes.
Original PR description
Version: - saas-19.3 Steps to reproduce: - Create a sign request using the eMSigner authentication method. - Complete the signing process. - Download the completed document. Issue: - Users received the original uploaded PDF instead of the signed PDF after completing the signing process through eMSigner. Cause: - After the BinaryValue migration, the completed document was initialized with the original document (document.raw) and only replaced with the eMSigner response for large compressed files. As a result, non-compressed responses stored the original document instead of the signed PDF returned by eMSigner. Fix: - Always use the signed document returned by eMSigner (decrypted_data) to create the completed document. Decode the base64 response and, for large files, decompress it before storing it as binary content. task-6329040
Importing product categories could fail when the parent category name appeared more than once in the system, causing a blocking warning during import. This fix makes category imports work more reliably, so users can bring in category data without unnecessary import errors.
Original PR description
When trying to import Product Categories, importing the Parent Category may raise blocking warnings. Steps to reproduce: - Open Sales > configuration > Categories - Import records - Select a file containing the parent category name - Import category name and parent category Issue: A warning will raise Found multiple matches for value "Furniture" in field "Parent Category" (2 matches) It occurs because, while searching by name, the system will use the complete name of the category so it will match multiple times the same name. This behaviour has been introduced in https://github.com/odoo/odoo/pull/236067/changes/0f788b8105c715681d67fdac04fa82c4c4d48e5e opw-6283004 Forward-Port-Of: odoo/odoo#271862
This fix ensures payroll payruns use the company the user selected, instead of incorrectly falling back to the main company. It prevents blocking warnings during payrun creation for branch companies, including the Hong Kong localization.
Original PR description
[FIX] hr_payroll: fix correct company selection in payrun (branch case) Bug reproduc: 1 - Select 19.3 or master -> Open a branch to belgium company -> create an employee in that branch 2 - In your…
[FIX] hr_payroll: fix correct company selection in payrun (branch case)
Bug reproduc:
1 - Select 19.3 or master -> Open a branch to belgium company -> create an employee in that branch
2 - In your env, select both belgium and its branch, payroll->payrun->select branch as a company.
3 - Continue till the end of payrun creation, you will get warning (blocked) due to wrong company selection, main belg company is selected instead of branch
Bug cause:
1 - In selectEmployees function of hr_payslip_run_form, in the raw_record the company_id is passed as integer.
2 - In buildRawRecord function of hr_version_list_controller, we are assigning company_id as raw_record's company_ids id, but company id was already integer, company_id.id is undefined
3 - Since undefined is passed to the company_id, it uses the self.env.company_id as a default in the creation of hr payrun that cause to the error.
Bug fix:
1 - In the buildRawRecord function of hr_version_list_controller, I just assigned the company_id because it is already integer and all problem is solved.
task - 6326117Invoices in Saudi Arabia and the UAE will now show the invoice title in the customer’s language instead of always defaulting to English. This improves the clarity and professionalism of printed invoices for Arabic-speaking customers.
Original PR description
### Issue: On invoices in SA and AE, the invoice title was always rendered in English even when the customer's language is Arabic ### Cause: In 19.2, the report view `report_invoice_document` was…
### Issue: On invoices in SA and AE, the invoice title was always rendered in English even when the customer's language is Arabic ### Cause: In 19.2, the report view `report_invoice_document` was refactored to require `t-set` declarations before `t-call` In 19.1, `o` was reassigned early with the customer language via `t-value="o.with_context(lang=lang)"`, so all subsequent calls on `o` inherited the correct language https://github.com/odoo/odoo/blob/3d2d8cc498a56faac31e95fb854a94e4011d812d/addons/account/views/report_invoice.xml#L4-L6 After the refactor, `o` no longer carries the customer language context at the point where `l10n_gcc_settings` is evaluated `_l10n_gcc_get_invoice_title()` was therefore called with the connected user's language instead of the customer's ### Steps to reproduce: - Install `l10n_sa` or `l10n_ae` and switch to the corresponding company - Create and confirm an Invoice (any data) - Set the customer language to Arabic - Print the Invoice Before the fix, the invoice title is displayed in English opw-6333472 Forward-Port-Of: odoo/odoo#272865
This update fixes an issue in Guatemalan electronic invoicing where names with accented or special characters could be rejected or arrive corrupted. By sending the invoice in the correct format, Odoo helps ensure invoices are certified reliably and customer or product names stay intact.
Original PR description
**Steps to reproduce:** * Install the **l10n_gt_edi** module. * Configure a Guatemalan company with valid Infile credentials in the settings. * Create a product or customer with special characters…
**Steps to reproduce:**
* Install the **l10n_gt_edi** module.
* Configure a Guatemalan company with valid Infile credentials in the settings.
* Create a product or customer with special characters (e.g. `ñ`, `á`, `é`) in their name.
* Create a customer invoice containing this product/customer.
* Confirm the invoice to trigger the EDI send to the SAT (Infile).
**Observed behavior:**
* Infile intermittently rejects the invoice due to validation errors, or accepts it but the resulting certified XML has truncated or malformed text exactly where the special characters were located.
**Cause:**
* Odoo uses the `requests.post()` library to send the XML payload to Infile. By default, `requests` encodes string payloads using `latin-1` unless told otherwise.
* Because the request was missing the explicit `Content-Type: application/xml` header and the XML string was not explicitly encoded to `utf-8` before sending, Infile parsed the payload using an incorrect encoding. This caused it to drop or misinterpret special characters, leading to validation failures or corrupted XML content.
**Fix:**
* Explicitly include the `'Content-Type': 'application/xml'` header in the request to Infile.
* Explicitly encode the `xml_data` payload to `utf-8` (`xml_data.encode('utf-8')`) before passing it to `requests.post()` to guarantee the correct encoding is sent over the wire.
opw-6315654
Forward-Port-Of: odoo/enterprise#121729This change prevents an error that could appear when deleting a newly created Receipt. It makes the status bar handle cases where nothing is selected, so users no longer see a traceback during this action.
Original PR description
# How to reproduce - Create a new Receipt - Save - Delete the new Receipt # The issue A traceback is shown : `TypeError: Cannot read properties of undefined (reading 'label')` # Cause This is caused…
# How to reproduce - Create a new Receipt - Save - Delete the new Receipt # The issue A traceback is shown : `TypeError: Cannot read properties of undefined (reading 'label')` # Cause This is caused by the custom status bar for pickings `StockPickingLockedStatusBarField`. In its template, we replace the display of the current label : https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.xml#L20-L23 https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.xml#L4-L9 The issue is that the base implementation of the current label properly handles the case were no item is currently selected: https://github.com/odoo/odoo/blob/7630f8fe2d5198b7a1ed538241795dc26a497fa0/addons/web/static/src/views/fields/statusbar/statusbar_field.js#L298-L300 But the picking implementation does not : https://github.com/odoo/odoo/blob/490c355ae0bc77c1106e22b3afb2206583980324/addons/stock/static/src/fields/stock_picking_locked_statusbar_field.js#L12-L14 And it seems that the template is quickly rendered without any selected item before deletion. opw-6345192 Forward-Port-Of: odoo/odoo#273030
Employees can now submit an expense even if they do not have a manager assigned, avoiding an error that blocked the process. They can also continue adding comments and attachments on their own expenses after they are no longer in draft, making it easier to provide explanations or extra proof when needed.
Original PR description
# [FIX] hr_expense: Submitting an expense without a manager doesn't work If a user tries to submit an expense without having a manager, this will fail with "You are neither a Manager nor a HR Officer". To fix this, we are not going to check when the manager is the user that expense is linked to. --------- # [FIX] hr_expense: Employee cant use chatter on his own expenses An employee that created his expense was only able to add attachments and post message in the chatter when the expense was in draft. After this, it will still be able to attach attachment and post message without having the right to edit the expense. This is better as the employee will be able to answer questions that have been asked or add more proof if required. [task-4966942](https://www.odoo.com/odoo/all-tasks/4966942) Forward-Port-Of: odoo/odoo#273067 Forward-Port-Of: odoo/odoo#224575
This change prevents an error that could occur when generating the Excel version of the GSTR-1 report for one company while data from another company is also present. It ensures the report can be exported normally without interruption, improving reliability for businesses working with multiple Indian company records.
Original PR description
Steps to reproduce: - Install `l10n_in_reports` module(Indian Localisation) - Create a branch in `IN Company` > Select both - Create separate invoices for each company - Created the GSTR-1 report for…
Steps to reproduce:
- Install `l10n_in_reports` module(Indian Localisation)
- Create a branch in `IN Company` > Select both
- Create separate invoices for each company
- Created the GSTR-1 report for both company
- While generating Excel, select only main company
Traceback:
```py
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 2537, in action_generate_gstr1_xlsx
gstr1_json = self._get_l10n_in_gstr1_json()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 1071, in _get_l10n_in_gstr1_json
'b2cs': _get_b2cs_json(AccountMoveLine.search(self._get_section_domain('b2cs'))),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/19.0/l10n_in_reports/models/account_return.py", line 672, in _get_b2cs_json
for line, line_tax_details in tax_details.items():
^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'items'
```
Cause:
This issue occurs because, while generating the GSTR-1 Excel report for a particular month, [journal_items] contains account moves from both companies. This happens because the [domain] fetches records for both companies, resulting in move [lines] from both companies being included.
However, while generating the Excel report, only one company is selected. As a result, [tax_details_by_move] does not contain the move data for the branch company, which returns None, causing the error to be raised.
Solution:
Pass an empty `{}` for `tax_details` when only a single company is selected.
[journal_items]: https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L877
[domain]: https://github.com/odoo/enterprise/blob/770ffaac14bfcd2c54a7ce6aca27e0010e7884d4/l10n_in_reports/models/account_return.py#L1387-L1393
[lines]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L1074
[tax_details_by_move]:
https://github.com/odoo/enterprise/blob/3c3641d9f0753c1ca62285667c4a2786c15e2444/l10n_in_reports/models/account_return.py#L880
opw-6242824
Forward-Port-Of: odoo/enterprise#118614This update corrects how the current year result is classified in Luxembourg accounting and simplifies the calculation of the balance sheet’s carried-forward profit or loss line. It helps ensure the report reflects the right figures more reliably in local financial statements.
Original PR description
This commit addresses the account type for the current year earnings and simplifies the calculation for the "Result brought forward" line in the Luxembourg balance sheet reports.
Modifications:
* Changed the account type of account 142 ("Result for the financial year") from `equity_unaffected` to standard `equity`.
* Simplified the formula for the Balance Sheet line "Profit or loss brought forward" (codes `LU_BS_319` and `LU_BSABR_319`).
* The new formula simply targets the `14` accounts while explicitly excluding `142`.
Enterprise PR: odoo/enterprise#121891
Ticket [link](https://www.odoo.com/odoo/project.task/6059571)
opw-6059571
Forward-Port-Of: odoo/odoo#272824
Forward-Port-Of: odoo/odoo#272362This update corrects how the current year result is classified and simplifies a balance sheet line in the Luxembourg reports. It helps ensure the financial statements show the carried-forward profit or loss more accurately and consistently.
Original PR description
This commit addresses the account type for the current year earnings and simplifies the calculation for the "Result brought forward" line in the Luxembourg balance sheet reports.
Modifications:
* Changed the account type of account 142 ("Result for the financial year") from `equity_unaffected` to standard `equity`.
* Simplified the formula for the Balance Sheet line "Profit or loss brought forward" (codes `LU_BS_319` and `LU_BSABR_319`).
* The new formula simply targets the `14` accounts while explicitly excluding `142`.
Community PR: odoo/odoo#272362
Ticket [link](https://www.odoo.com/odoo/project.task/6059571)
opw-6059571
Forward-Port-Of: odoo/enterprise#122097
Forward-Port-Of: odoo/enterprise#121891