Daily updates from Odoo
Wednesday, May 20, 2026
268 changes
26 changes
Resolved issues and error corrections
This update ensures that UTM tracking parameters (like those used for marketing campaigns) are correctly processed when the website's cookies bar is displayed. Previously, these parameters weren't handled properly. This change improves the accuracy of marketing data collected through the cookies bar.
Original PR description
Since we've added the utm_reference parameter, it should be correctly handled in when the cookies bar is present Added in: https://github.com/odoo/odoo/pull/233963 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#265011
This update fixes a test for the HTML editor that was unreliable due to its dependence on timing and browser behavior. The change makes the test more stable and predictable, especially on slower computer systems, ensuring consistent test results.
Original PR description
Description of the issue this PR addresses: Previously the test relied on real timers, animation frames and simulateArrowKeyPress(), making it sensitive to browser scheduling, native selectionchange timing and CPU slowness. The test now: - use advanceTime() instead of real setTimeout() - Replace simulateArrowKeyPress() with manual selectionchange dispatch to make debounce scheduling deterministic and avoid relying on the browser's asynchronous native selectionchange dispatch. - Add patchWithCleanup + verifySteps to test actual debounce execution rather than DOM visibility timing, which is sensitive to rendering and brwoser scheduling variance. This removes timing races and stabilizes the test on slow CI workers. runbot-242466 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264893
This update resolves a crash during KSeF certificate authentication caused by Odoo not properly handling different certificate types. The fix automatically determines the correct identifier type, ensuring successful authentication and compliance with Polish tax regulations. This improves the reliability of the Odoo system for businesses using KSeF.
Original PR description
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400…
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400 Client Error: Bad Request for url: https://api.ksef.mf.gov.pl/v2/auth/xades-signature"_ This is due to Odoo not handling different `SubjectIdentifierType` **Solution**: Implement a try/except block to safely check for the NIP in the certificate's subject string, defaulting the identifier type to `certificateFingerprint` when the NIP is missing or a ValueError is caught. ### Current behavior before PR: The `SubjectIdentifierType` is hardcoded as `certificateSubject`, and does not handle `certificateFingerprint` at all. This causes there to be an error when trying to authenticate with the KSeF server using XAdES signature. ### Desired behavior after PR is merged: The sign_authentication_challenge method will now safely evaluate the subject string. It assigns `certificateSubject` only if the NIP is verified to be in the subject string. If the NIP is absent or a ValueError occurs during parsing, the system safely falls back to using `certificateFingerprint`. This prevents tracebacks and ensures the correct XML payload is sent to the KSeF server. Ticket [link](https://www.odoo.com/odoo/project.task/6125243) opw-6125243 Forward-Port-Of: odoo/odoo#264851
This update resolves an issue where product category images weren't showing correctly on website B when accessed without being logged into website A. The fix ensures category images use absolute URLs, bypassing domain-based access rules that were causing the display to fail. This improves the visual consistency of product categories across all websites.
Original PR description
Scenario: - set two website A and B with different domain - create an eCommerce category Y - create and publish a product with category Y, website B - drop category list widget in a page in website B - set in /odoo/system-parameters web.base.url to domain of website A - open the page in website B while being logged out of website A Result: the category Y image is dead. Cause: category images are using domain of "web.base.url", so if that corresponds to a website where the category is not shown (because of the access rule "Hide empty eCommerce categories to public/portal users") then the image will not be shown (unless we are a logged in internal user on the domain of "web.base.url"). Fix: use absolute URL without domain for category image, the same way it is done for other dynamic snippets (eg. Products). opw-6118004 Forward-Port-Of: odoo/odoo#260124
This update corrects a bug where a course would remain active even after all orderlines were removed, preventing table release. The fix automatically cleans up empty courses when the last orderline is deleted, ensuring the system functions correctly and tables can be released efficiently.
Original PR description
Steps to reproduce: - add a course - add a orderlines - remove orderlines - the course is still there - unable to release table Fix: Call cleanCourses after removeOrderline so empty unfired courses are automatically deleted when the last orderline of a course is removed. Task-6181153 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#262818
This update corrects a technical issue preventing Croatian invoices with alphanumeric premises labels (like 'v1') from processing correctly. The change adjusts a key system rule to accept these labels, ensuring invoices are properly generated and processed without errors. This resolves a previous traceback and improves invoice confirmation functionality.
Original PR description
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's…
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's tooltip. However, the regex pattern inside `_get_l10n_hr_fiscalization_number` used to extract the sequence parts strictly expected digits (`\d+`) for the premises label segment. Because of this, if an invoice was generated with an alphanumeric sequence like `INV-2026-0001/v1/1`, the regex failed to match and returned `False`, leading to a traceback when the system attempted to process the fiscalization number. This commit updates the regex to correctly accept alphanumeric characters for the premises label, ensuring the sequence parses successfully. opw-6129009 ### Steps to reproduce: - Settings > Users & Companies > Companies > New > set Address country to Croatia - Select the newly created Croatian company - Apps > Activate l10n_hr_edi module - Accounting > Configuration > Accounting > Journals > click Sales journal > change “Business premises label” to “v1” - Contacts > New > set Address country to Croatia - Accounting > Customers > Invoices > New > select the newly created contact and choose any product > Confirm ### Current behavior before PR: Traceback error when attempting to confirm an invoice when both the company and the customer have their country code set to 'HR'. This is because `_get_l10n_hr_fiscalization_number` does not accept alphabet characters in the premises label section of the regex. ### Desired behavior after PR is merged: - No traceback error when confirming the invoice - `_get_l10n_hr_fiscalization_number` correctly parses the fiscalization number Forward-Port-Of: odoo/odoo#263650
This update fixes a potential crash during bank statement imports caused by incorrect journal selection. The system now automatically validates currency and IBAN matches, ensuring the correct journal is used and preventing user errors. This improves the reliability and accuracy of importing bank statement data.
Original PR description
Behavior before: The import flow could crash with an "Expected singleton" error if multiple journals shared an IBAN. Additionally, the system blindly accepted the current context ('self') as the…
Behavior before:
The import flow could crash with an "Expected singleton" error if multiple
journals shared an IBAN. Additionally, the system blindly accepted the
current context ('self') as the target journal, even if its currency or
bank account mismatched the statement, often leading to avoidable
UserErrors.
Behavior after:
The system now validates 'self' against the statement's currency and IBAN
before assignment. If a mismatch is found, it automatically searches for
the correct journal. The search is now restricted by currency and includes
a limit=1 to prevent crashes and ensure accurate selection.
Root Cause:
In _find_additional_data(), 'journal = self' was assigned without validation.
Furthermore, the fallback search lacked a record limit and currency matching
logic, allowing multiple records to be returned when duplicates or
multi-currency setups existed.
Fix:
- Added validation for the initial 'self' candidate (currency and IBAN match).
- Refined the search domain to include currency matching (journal or
company fallback).
- Added limit=1 to the search to guarantee a singleton recordset.
opw-5462037
Forward-Port-Of: odoo/enterprise#117394
Forward-Port-Of: odoo/enterprise#115475This update aligns MPF contribution rules in Hong Kong with a standard age range (18 to under 65), ensuring accurate payroll calculations. It simplifies contribution eligibility checks and brings consistency across EEMC/ERMC contributions, resolving a previous inconsistency in reporting. This change improves the accuracy of MPF reporting and simplifies compliance.
Original PR description
### Before: - Mandatory MPF rules only checked the upper age bound (< 65 from period start). - Employees under 18 could still be considered eligible for EEMC/ERMC contributions. - eMPF reporting had a separate 16-year age check. - Employees younger than 16 were excluded from the eMPF report, even when they had voluntary contributions. ### After: - Mandatory MPF rules now apply a full age gate (18 to under 65) across the payslip period. - EEMC and ERMC use the same eligibility condition for consistent contribution behavior. - The eMPF reporting age check is now aligned to 18. - Employees under 18 remain excluded from eMPF reporting unless they have actual MPF contributions. - Under-18 employees with voluntary contributions are now included in the eMPF report, matching the existing over-65 voluntary contribution behavior. --- Task-6141664
A recent update (saas-19.3) introduced an unwanted gap between the Studio navigation bar and the apps section on the home page. This fix removes the problematic margin and adjusts spacing for the search input, restoring the intended visual appearance and preventing background exposure.
Original PR description
Since saas-19.3, an extra margin on the home menu introduced a visible gap between the Studio navbar and the apps section, exposing the background. This commit removes the margin from the o_home_menu and applies spacing to the search input instead. task-6175467 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue causing the Odoo tour to become unpredictable. The fix ensures the sliding panel fully closes before proceeding, preventing a race condition that previously disrupted the tour flow. This enhances the user experience and ensures consistent tour functionality.
Original PR description
This commit stabilizes the tour flow by ensuring the sliding panel is fully closed before proceeding to the next step. Issue: The tour steps selects a shape, which triggers [hideSlidingPanel]. That…
This commit stabilizes the tour flow by ensuring the sliding panel is fully closed before proceeding to the next step. Issue: The tour steps selects a shape, which triggers [hideSlidingPanel]. That function focuses a `BuilderButton` after a timeout. This introduced a race condition: if the timeout executes before the tour interacts with the `OverlayButtons`, the overlay gets hidden due to the `focusin` event registered on the builder (outside the iframe) [1], which ultimately hides the overlay buttons. The issue made the tour undeterministic following commit [2], which removed several intermediary steps between the shape selection and the failing step. Fix: Wait for the sliding panel to fully close before continuing the tour flow. [hideSlidingPanel]: https://github.com/odoo/odoo/blob/saas-19.3/addons/html_builder/static/src/core/building_blocks/builder_sliding_panel.js#L73-L81 [1]: https://github.com/odoo/odoo/blob/saas-19.3/addons/html_editor/static/src/core/selection_plugin.js#L265 [2]: https://github.com/odoo/odoo/commit/fa328f4e1798a9547e9df749c4144478357e1764 runbot-[242702](https://runbot.odoo.com/odoo/error/242702)
This update resolves an error that occurred when users removed the 'Source Entity Id Type' setting in the Super Contributions module. The fix ensures the system correctly handles this removal, preventing a data processing error and maintaining accurate reporting. This improves the stability of the Australian payroll functionality.
Original PR description
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an…
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an `Australian` company. - Go to `Payroll` > `Reporting` > `Australia` > `Super Contributions`. - Open an existing record or create a new one. - Remove the `Source Entity Id Type` value and click anywhere. `ValueError: Compute method failed to assign l10n_au.super.stream(<NewId origin=1>,).source_entity_id` After [change] in the selection field behavior, when the user removes the Source Entity Id Type, the compute method is triggered to compute the Source Entity ID. However, the condition in the compute method is not match, so no value is assigned. As a result, the method fails and raises an error. This commit ensures that if the condition is not match, the Source Entity ID is explicitly set to False. [1]- https://github.com/odoo/enterprise/blob/9d523d7aabffda277e1ef734caf2b0e434545dca/l10n_au_hr_payroll_account/models/l10n_au_super_stream.py#L61-L65 [change]: https://github.com/odoo/odoo/pull/214422/changes/8d2a42ac419fdf7943a0c11beb8c5de6c6f85bef Forward-Port-Of: odoo/enterprise#115466
This update resolves a usability issue in the composer where adding text to a seemingly blank line would hide it within the user signature. The fix moves the formatting code outside the signature container, preventing accidental text encapsulation and improving the composer's clarity for users. This ensures consistent and predictable signature behavior.
Original PR description
**Steps to reproduce:** - Go to the chatter of any record - Open the full composer - Empty line is present above the signature delimiter (`--`) - Adding text to this line will encapsulate it with the rest of the signature (and hide it by default in the message) **Issue:** Extra `<br>` was added to improve readability, but adding it this way (before the delimiter) can be confusing for the users as they can add text on what appears to be a normal empty line, that is actually hidden with the signature ellipsis. **Fix:** Moved the added `<br>` element outside the signature container for the full composer. The user can still find a way to modify the composer structure in a way that will hide part of the text (e.g. by typing just before the delimiter), but this limits the issue. related: https://github.com/odoo/odoo/commit/13a9c6f5010c3dee01aa0f66ed41b25f517a4a8c opw-6087042 Forward-Port-Of: odoo/odoo#257936
This update resolves an issue where archived sales teams were incorrectly showing up in the Sales Team dropdown when creating new opportunities within the CRM. The fix removes a redundant setting that was causing this behavior, ensuring accurate dropdown lists for active and archived teams. This improves the user experience and data consistency.
Original PR description
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and…
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and stage dropdowns. Creating an opportunity from the CRM app does not have this issue.
`res.partner.action_view_opportunity` sets `active_test: False` in the action context so archived opportunities show up in the list view. That context is passed down to the form opened from the action, and to every search the form runs to fill its dropdowns. So the dropdowns also return archived records.
The action's domain already has `('active', 'in', [True, False])`, which is enough to keep archived opportunities in the list on its own (the ORM only adds the "active = True" filter when `active` is not already in the domain). So we can just remove `active_test: False` from the context. This is what 18.0 was doing before https://github.com/odoo/odoo/commit/59feed9f26937ae8e2cab5cd7d2b6743ab6c0717 put the context flag back in.
The override in `website_crm_partner_assign` was setting `active_test: False` back on the action context for the same reason (so its extra search for assigned leads picks up archived ones). The flag is now applied locally on the `crm.lead` handle used for those searches, so archived leads are still found without polluting the action's context.
Steps to reproduce:
1. Archive a Sales Team in CRM > Configuration > Sales Teams
2. Open the Contacts app and pick any contact
3. Click the Opportunities smart button
4. Click "New" and open the Sales Team dropdown
=> Archived teams appear in the dropdown
Ticket [link](https://www.odoo.com/odoo/project.task/6134801)
opw-6134801
Forward-Port-Of: odoo/odoo#263283
Forward-Port-Of: odoo/odoo#261300This update ensures that donation confirmation emails are sent in the user's chosen website language, regardless of their anonymous status. Previously, emails were defaulted to English. This change improves the user experience and ensures consistent communication for all donors.
Original PR description
Steps to reproduce: =================== 1. Configure website with at least 1 language installed different from English. ex: English and French. 2. As anonymous user, change wehbsite language and make…
Steps to reproduce: =================== 1. Configure website with at least 1 language installed different from English. ex: English and French. 2. As anonymous user, change wehbsite language and make a donation via the donation snippet. 3. Check the outgoing confirmation email. => Email body is rendered in English. Cause: ====== The donation confirmation email rendered with `self.partner_id.lang`. For anonymous donors, `partner_id` is the website's shared public user partner, so every anonymous donor received the email in whatever language was set on that partner (or English if unset), regardless of the language they were browsing in. Solution: ========= `payment.transaction` already has a `partner_lang` field auto-filled from `partner.lang` at creation. - override it in the `/donation/transaction` controller with `request.env.lang` when the public partner is used, capturing the request language at donation time (also works later from `_cron_post_process`, which has no request context); - render `_send_donation_email` using `self.partner_lang` instead of `self.partner_id.lang`. opw-5875338 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264657 Forward-Port-Of: odoo/odoo#259351
This update fixes a minor error in the Odoo software's configuration for Mexican accounting. The change corrects a typo in the account group data, ensuring accurate reporting and compliance with Mexican tax regulations. This ensures the software functions correctly within the Mexican market.
Original PR description
Source: https://www.sat.gob.mx/minisitio/NormatividadRMFyRGCE/documentos2026/rgce/anexos/Anexo24delasRGCEpara2026.pdf opw-6174385 Forward-Port-Of: odoo/odoo#262549
This update prevents the system from wasting time attempting to create API keys for unreachable databases. Previously, errors would clutter the synchronization results and cause delays. Now, the system skips these databases, improving synchronization speed and user experience.
Original PR description
#### The aim of this commit is to: - avoid cluttering the user UI with "obvious" error. - avoid wasting up to 15s trying to create the key if we don't get any response. #### Context: When a db is unreachable, trying to create an api-key on it will result in an error. #### Before this commit: - The wizard showing the result of the synchronization would show the error for every single databases in which it encounters that error. If there are a lot, it would bloat the result. - An unresponsive db would waste 15s of our sync time in a synchronized process. If that happens multiple times, we could end up a lot of time waiting for no reason. #### After this commit: We don't try to create an api key for unreachable databases. task-id: [5945269](https://www.odoo.com/odoo/project.task/5945269) - follow up Forward-Port-Of: odoo/enterprise#117053
This update fixes a potential issue in the Point of Sale system by separating the waiter method. This change allows for more flexible error handling, particularly important for features like FDM where order validation needs to be paused during errors. It ensures the system can continue to function correctly even when issues arise.
Original PR description
In order to allow patching (in particular for FDM, where we don't want to finalize the validation of the order if there is an error), we extract the waiter method. see odoo/enterprise#104468 Forward-Port-Of: odoo/odoo#264974 Forward-Port-Of: odoo/odoo#244298
This update fixes an issue where the Point of Sale (PoS) displayed incorrect order totals due to delays in processing. The change ensures the correct order price is calculated and displayed on the feedback screen, preventing zero amounts and improving the user experience. It also includes safeguards to prevent order validation errors.
Original PR description
We now call manually `setOrderPrices` on order validation to ensure `amount_total` is set on the order before displaying the feedback screen which depends on it. The issue is that requests to the FdM delay the call to this method, making the PoS display `0` as the amount is `undefined` in the meantime. We also ensure the PoS doesn't finalize the validation if an error occurs. see odoo/odoo#244298 Forward-Port-Of: odoo/enterprise#117594 Forward-Port-Of: odoo/enterprise#104468
A test for multi-lot component consumption was failing due to a missing user group. This update explicitly grants the necessary 'lot tracking' group within the test environment, ensuring the test now passes correctly. This resolves a technical issue that could have impacted future development.
Original PR description
The test uses the stock move line detailed operations form and expects the `lot_id` field to be present in the view. Without demo data, the current user may not belong to the `stock.group_production_lot` group, causing the field to be absent from the rendered form view and the test to fail. Causing: `AssertionError: 'lot_id' was not found in the view` in line: https://github.com/odoo/odoo/blob/0442c66d26b0c23313f17c566b16e34e7b22c2b6/addons/mrp/tests/test_consume_component.py#L477 Grant the lot tracking group explicitly in the test setup. runbot-243588 Forward-Port-Of: odoo/odoo#263759
This update fixes a visual inconsistency in the CRM form view. Previously, MRR and AI probability fields were displayed on separate lines, causing misalignment across devices. Now, both fields are aligned on a single line for a cleaner and more consistent user experience on both desktop and mobile.
Original PR description
**Before this commit:** When recurring revenues were enabled in CRM, the MRR field was displayed across two lines instead of a single line as expected. In mobile view, the AI probability was displayed as a separate input field, instead of a same line. Commit: https://github.com/odoo/odoo/commit/cfef0dde9df8d1999e6aad0a28dbfd11049d19d8 **After this commit:** Updated the form view layout to display both the MRR and AI probability fields on a single line for better alignment and consistency across desktop and mobile views. Task-6128227
This update resolves an issue where Odoo was attempting to process GSTR2B attachments with missing file content, leading to errors. The change now verifies that the attachment's actual file data exists before processing, ensuring smoother return filing and preventing potential disruptions. This improves the reliability of the Invoicing reports.
Original PR description
There may be databases contained GSTR2B JSON attachments whose metadata was still present in `ir.attachment`, but whose underlying binary content was missing from the filestore. This caused the matching flow to attempt processing invalid JSON payloads instead of moving the return to `error_in_fetching`. The condition validating JSON attachments now also checks that the attachment raw content exists before adding it to the payload list. opw-6088082 Forward-Port-Of: odoo/enterprise#117083
This update corrects a technical error that prevented users from interacting with the 'Test' button within the IoT app. The issue stemmed from a data processing error, specifically an 'index out of range' error, which was preventing the button from functioning correctly. This fix ensures the 'Test' button operates as intended.
Original PR description
This PR fixes the following traceback when using "Test" button in the iot app: ``` 2026-05-18 07:48:36,248 22727 ERROR ? websocket: error from callback <bound method WebsocketClient.on_message of <WebsocketClient(Thread-6, started daemon 3995071456)>>: list index out of range 2026-05-18 07:48:36,249 22727 ERROR ? odoo.addons.iot_drivers.websocket_client: websocket received an error: list index out of range ``` opw-6226014 Forward-Port-Of: odoo/odoo#264897
This update resolves a limitation in the sale commission report's query, allowing it to handle significantly larger sales order IDs. By removing an unnecessary bit shift, the report now supports a much wider range of data, improving performance and scalability. This change ensures the report continues to function correctly with growing sales volumes.
Original PR description
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs.…
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id <<10` This shifts the max aml.id 40 bits to the left. Example: Let's say MAX(aml.id) = 1; we will set the other variables to 1, as they often have little impact on the total size of the number. 1 << 20 = 1048576 1048576 | 1 = 1048577 1048577 << 10 = 1099512676352 1099512676352 | 1 = 1099512676353 1099512676353 << 10 = 1152922604119523328 With this format, the highest guaranteed AML ID this query can handle is under 838,861. The last 10-bit shift is unnecessary and increases the result. If we remove the last shift, the AMD ID this query can handle becomes much higher. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id` | | AML Max | RULES.ID Max |RULES.USER_ID Max| | --------------------- | ------ | ------ | ------ | | Before | 838,861 | 1,048,576 | 1,024 | | After | 858,993,459 |1,048,576 | 1,024| opw-6124026 Forward-Port-Of: odoo/enterprise#114711
This update fixes an issue where returned subcontracted products were incorrectly routed to the subcontractor's location instead of the user's stock. When returning products 'for exchange', the system now correctly directs returned items to the subcontractor's location and new deliveries to the user's stock, ensuring accurate inventory tracking during the subcontracting process. This prevents misallocation of stock and improves reporting accuracy.
Original PR description
## Issue When making a request for quotation for a subcontracted product and returning the delivery "for exchange", the new incoming delivery does not have the correct destination. Instead of having…
## Issue
When making a request for quotation for a subcontracted product and returning the delivery "for exchange", the new incoming delivery does not have the correct destination. Instead of having the stock of the user, the destination of the new incoming delivery is the same as its source: the subcontracting location.
<img width="1254" height="257" alt="5479900" src="https://github.com/user-attachments/assets/c7e6d392-8328-4a03-a71e-466e768f448b" />
## Steps to reproduce
1. Install MRP Subcontracting (`mrp_subcontracting`) and Purchase (`purchase`)
2. In Settings, enable *Subcontracting*
3. Create a Product P and a subcontracting BoM with Subcontractor S
4. Create a Request for Quotation
- Vendor: Subcontractor S
- Product: Product P (any quantity > 0)
5. Confirm the RFQ, receive the PO, validate the picking
6. On the validated picking, click *Return*, set the quantity of products to return, and click *Return for Exchange*
- This creates two new pickings, one to return the product(s) we received, and one to receive new products
7. Validate the two new pickings
8. **In Inventory > Reporting > Moves History, the very last `stock.move.line` has the same location in the *From* (`location_id`) and the *To* (`location_dest_id`) columns**
## Cause
The `location_dest_id` of the new `stock.move` is updated in `StockReturnPickingLine._prepare_move_default_values`.
https://github.com/odoo/odoo/blob/fb534f1eadcb8ef74e2ee6fd5b68872dddb978e3/addons/mrp_subcontracting/wizard/stock_picking_return.py#L20-L25
The condition added by https://github.com/odoo/odoo/commit/5404b426aac9 sets the destination of all returned subcontracted moves to the subcontractor location. This is incorrect when using "return for exchange", as in this case, the return move is directed towards the user's stock. In fact, when using "return for exchange", the following pickings are created:
| id | name | return_id | |
|:--:|--------------|:---------:|---|
| 1 | WH/IN/00001 | | Initial RFQ delivery |
| 2 | WH/OUT/00001 | 1 | Return of the initial RFQ delivery |
| 3 | WH/IN/00002 | 2 | New products delivery to replace the initial delivery. The stock.move.line of this stock.picking has a wrong `location_dest_id` |
## Fix
In the context of return for exchanges, the returned item must be directed to the *Subcontracting Location* while the new item must be directed to the *Stock*. In the `_prepare_move_default_values`, we should only set the `location_dest_it` to the subcontractor location for outgoing pickings.
opw-5479900
Forward-Port-Of: odoo/odoo#265071
Forward-Port-Of: odoo/odoo#245905This update fixes an issue where project update descriptions incorrectly showed inflated budget totals after budget revisions. The fix ensures that only the active, confirmed budget revision is used, providing accurate budget information for project updates. This improves the clarity and reliability of project financial reporting.
Original PR description
**Problem:** When a project analytic budget is revised, the project update description shows an inflated total budget — the sum of both the original and the revised amounts — instead of reflecting…
**Problem:** When a project analytic budget is revised, the project update description shows an inflated total budget — the sum of both the original and the revised amounts — instead of reflecting only the active (confirmed) revision. **Steps to reproduce:** 1. Create a project with an analytic account 2. Create an analytic budget of $10,000 and confirm it 3. Create a revision of that budget for $15,000 and confirm it 4. Create a new project update 5. The update shows "$25,000" as the total budget instead of "$15,000" **Current behavior:** The project update displays the sum of all budget revisions ($25,000), regardless of their state. **Expected behavior:** Only the active confirmed budget ($15,000) should be used. **Cause of the issue:** `_compute_budget` queries all `budget.line` records matching the project's analytic account without filtering by the parent `budget.analytic` state. When a budget is revised, the original transitions to state `revised` while the new one becomes `confirmed`. Because `_compute_budget` has no state filter, it sums both, producing an inflated `total_budget_amount`. This field is then used in the project update template to compute the displayed budget total and percentage. By contrast, `_get_budget_items` — used for the detail rows — already applies `state in ['confirmed', 'done']`, so the two methods were inconsistent. **Fix:** Applying the same state filter to `_compute_budget` as already present in `_get_budget_items` ensures both methods draw from the same set of active budgets, keeping the project update totals consistent with the budget detail rows. opw-6128855 Forward-Port-Of: odoo/enterprise#117490 Forward-Port-Of: odoo/enterprise#115285
This update clarifies the labels used for vehicle deductibility rates, ensuring they accurately represent the non-deductible portion. The previous labels were misleading, and this change improves the accuracy and clarity of financial reporting related to fleet vehicles.
Original PR description
The "Deductibility Rates" and "Deductibility (%)" labels are wrong for vehicles as they are supposed to represent the non-deductible part. This commit fixes these labels. task-6121629 Forward-Port-Of: odoo/enterprise#116878
24 changes
New functionality added to Odoo
This update introduces a simple LED flashing feature within the IoT app, triggered by a 'test' button. This allows technicians to easily identify and locate IoT boxes, particularly when multiple boxes are present in a setup like an OXP (Open Experience Point).
Original PR description
This PR adds a feature to flash red and green leds on the iot box with odoo-led-manager service when using "test" button in iot app This helps to identify an iot box when having multiple in the setup (Ex: OXP) Forward-Port-Of: odoo/odoo#263359
Enhancements to existing features
This update enhances the way message previews display links, ensuring they remain concise and consistent regardless of the original message's formatting. The changes simplify link previews by converting HTML elements to text, improving readability and usability for users.
Original PR description
Message previews should stay compact and predictable even when the original message contains rich HTML. This changes applies a narrow first-step conversion: - convert <br> to non-breaking spaces - insert spacing between adjacent block elements - flatten non-link elements to their text content - preserve links only as anchors displaying their href task-5263284
This update streamlines the invoicing process by automatically reconciling invoices created from sales orders. Previously, this required manual steps; now, the system directly links invoices to sales orders, improving efficiency and reducing the risk of errors. This enhancement is part of a larger effort to simplify financial workflows within the Odoo Enterprise system.
Original PR description
This commit will allow to automatically reconcile the invoice create from the sale order by passing a context key that will be used in the create_invoices function. task-5502964 Forward-Port-Of: odoo/enterprise#108546
This update allows users to omit email subjects when sending notifications in 'comment mode' within Odoo. Previously, a subject was automatically added, but this change provides more flexibility. This improves the user experience by allowing users to customize email notifications without requiring a subject.
Original PR description
In comment mode we use the regular message post flow rather than the optimized batch email creation of the composer. This notably means a fallback subject will normally be set. The subject is made optional in that context, and only mandatory in batch mode where the emails would otherwise truly not have a subject. task-5944635
Resolved issues and error corrections
This update fixes an error preventing branch companies from accessing and using bank accounts configured for their parent companies. Previously, attempts to pay invoices from branch accounts resulted in an access error. The change ensures branch companies have proper access to the bank accounts they're linked to, improving payment functionality.
Original PR description
**Steps to reproduce:**
- Install Accounting
- Create a branch company
- From parent company, configure Bank journal:
=> set its "Bank Account Number" to a bank account having its company field set
- Switch to the branch company
- Create an invoice
- Confirm the invoice
- Try to pay from the invoice
**Issue:**
An Access Error is raised because the bank account used for the payment belongs to the parent company and the branch company doesn't have access to it.
opw-6001573
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update resolves an issue where backorders couldn't be created after merging production orders, leading to a software error. The fix ensures that production groups are correctly managed during merging, preventing empty recordsets and subsequent errors. This improves the reliability of the backorder creation process.
Original PR description
# How to reproduce - Create 2 MO's A & B, both having the same product_id & bom_id - Split MO A into two MO's A1 & A2 - Merge MO's A1 & B # The issue MO A2 no longer has a production group (visible…
# How to reproduce - Create 2 MO's A & B, both having the same product_id & bom_id - Split MO A into two MO's A1 & A2 - Merge MO's A1 & B # The issue MO A2 no longer has a production group (visible via Studio). If the user tries to partially produce the MO and create a backorder, a traceback popup appears with : "ValueError: max() iterable argument is empty" # Cause The traceback is triggered because we use the `max()` function on `self.production_group_id.production_ids` when creating the backorder, but `production_ids` is an empty recordset since `production_group_id` is also empty. https://github.com/odoo/odoo/blob/0d8eaeeb971f2f670aebb1b72ed03f4a2d5e0105/addons/mrp/models/mrp_production.py#L1936 The production group is empty because when merging two MO's we delete it without paying attention to other remaining links. https://github.com/odoo/odoo/blob/394a30f8a2814d460cfe220b5017e7ac95d8cddc/addons/mrp/models/mrp_production.py#L2555 Note : the production groups were introduced by this commit (https://github.com/odoo/odoo/commit/2713876dbc70d3984e584a9037a2206dcda4e84a) # Proposed solution When merging, we unlink the original MO's from their production group. Then, we check every altered production group : if they are not linked to any MO anymore, we delete them. opw-6055376 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#256600
This update fixes a visual issue on the company's website where the first product variant shown wasn't always the correct one. By setting specific product sequences, the system now ensures the desired variant image appears prominently on category pages and in the product configurator, leading to a better customer experience.
Original PR description
When generating a product, set product.template.attribute.value sequences so that the variant that shows first in the external website is also first by _get_first_possible_variant_id(). This ensures the correct variant image appears on the shop category page and is pre-selected in the product configurator. Forward-Port-Of: odoo/enterprise#117701
This update fixes a test for the HTML editor that was unreliable due to its dependence on timing and browser scheduling. The change makes the test more stable and predictable, ensuring consistent results across our CI systems. This improves the overall quality and reliability of the HTML editor.
Original PR description
Description of the issue this PR addresses: Previously the test relied on real timers, animation frames and simulateArrowKeyPress(), making it sensitive to browser scheduling, native selectionchange timing and CPU slowness. The test now: - use advanceTime() instead of real setTimeout() - Replace simulateArrowKeyPress() with manual selectionchange dispatch to make debounce scheduling deterministic and avoid relying on the browser's asynchronous native selectionchange dispatch. - Add patchWithCleanup + verifySteps to test actual debounce execution rather than DOM visibility timing, which is sensitive to rendering and brwoser scheduling variance. This removes timing races and stabilizes the test on slow CI workers. runbot-242466 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264893
This update resolves a crash during KSeF certificate authentication caused by Odoo's inability to handle different certificate types. The fix automatically determines the correct identifier type, ensuring successful authentication with the KSeF server and allowing users to properly utilize the Polish tax system features.
Original PR description
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400…
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400 Client Error: Bad Request for url: https://api.ksef.mf.gov.pl/v2/auth/xades-signature"_ This is due to Odoo not handling different `SubjectIdentifierType` **Solution**: Implement a try/except block to safely check for the NIP in the certificate's subject string, defaulting the identifier type to `certificateFingerprint` when the NIP is missing or a ValueError is caught. ### Current behavior before PR: The `SubjectIdentifierType` is hardcoded as `certificateSubject`, and does not handle `certificateFingerprint` at all. This causes there to be an error when trying to authenticate with the KSeF server using XAdES signature. ### Desired behavior after PR is merged: The sign_authentication_challenge method will now safely evaluate the subject string. It assigns `certificateSubject` only if the NIP is verified to be in the subject string. If the NIP is absent or a ValueError occurs during parsing, the system safely falls back to using `certificateFingerprint`. This prevents tracebacks and ensures the correct XML payload is sent to the KSeF server. Ticket [link](https://www.odoo.com/odoo/project.task/6125243) opw-6125243 Forward-Port-Of: odoo/odoo#264851
This update fixes an issue where self-order receipts incorrectly displayed 'Service at Table' instead of 'Pickup At Counter' when a customer selected a counter service option without identification. This ensures accurate receipt information for customers using the self-order feature, improving the customer experience and order clarity.
Original PR description
When selecting a preset with a service at counter but without identification, after a self order the receipt header was wrongly showing "Service at Table" instead of "Pickup At Counter". This is now fixed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264115
This update corrects a bug where a course would remain active even after all orderlines were removed, preventing table release. The fix automatically cleans up empty courses when the last orderline is deleted, ensuring a smoother and more reliable restaurant order process.
Original PR description
Steps to reproduce: - add a course - add a orderlines - remove orderlines - the course is still there - unable to release table Fix: Call cleanCourses after removeOrderline so empty unfired courses are automatically deleted when the last orderline of a course is removed. Task-6181153 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#262818
This update resolves an issue where Croatian invoices with alphanumeric characters in the business premises label (e.g., 'v1') were causing system errors. The fix modifies a key parsing rule to correctly recognize and process these labels, ensuring invoices are processed without errors. This improves the reliability of the Croatian fiscalization process.
Original PR description
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's…
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's tooltip. However, the regex pattern inside `_get_l10n_hr_fiscalization_number` used to extract the sequence parts strictly expected digits (`\d+`) for the premises label segment. Because of this, if an invoice was generated with an alphanumeric sequence like `INV-2026-0001/v1/1`, the regex failed to match and returned `False`, leading to a traceback when the system attempted to process the fiscalization number. This commit updates the regex to correctly accept alphanumeric characters for the premises label, ensuring the sequence parses successfully. opw-6129009 ### Steps to reproduce: - Settings > Users & Companies > Companies > New > set Address country to Croatia - Select the newly created Croatian company - Apps > Activate l10n_hr_edi module - Accounting > Configuration > Accounting > Journals > click Sales journal > change “Business premises label” to “v1” - Contacts > New > set Address country to Croatia - Accounting > Customers > Invoices > New > select the newly created contact and choose any product > Confirm ### Current behavior before PR: Traceback error when attempting to confirm an invoice when both the company and the customer have their country code set to 'HR'. This is because `_get_l10n_hr_fiscalization_number` does not accept alphabet characters in the premises label section of the regex. ### Desired behavior after PR is merged: - No traceback error when confirming the invoice - `_get_l10n_hr_fiscalization_number` correctly parses the fiscalization number Forward-Port-Of: odoo/odoo#263650
A previous error prevented users from searching for links within the Link Tracker feature. This update resolves the issue, allowing users to accurately search for clicks based on their short URLs. The fix addresses a technical limitation with how the short URL field is currently handled.
Original PR description
Overview ------ When searching based on the `Link (short_url)` field in the search bar, in the `link.tracker.click` list view, an error fires up. How to Reproduce ------ 1. Open the Email Marketing…
Overview ------ When searching based on the `Link (short_url)` field in the search bar, in the `link.tracker.click` list view, an error fires up. How to Reproduce ------ 1. Open the Email Marketing app 2. Create a new mailing (or you can use an existing one that has some clicks) and send it 3. Make a click in the email from the recipient's side 4. Open the link tracker `click` related to that mailing (select the mailing → `Link Trackers` stat button → click on a link → `Clicks` stat button) 5. Make a search based on the Link (short_url) field Expected Behavior ------ Return the list of links that matches the entered search query. Current Behavior ------ Odoo Server Error. Cause & Solution ------ The cause of this error is that the `shor_url` field is a computed, non-stored, field, and hence, we cannot directly make a search on it. So, either we make the `short_url` a stored field, which is not so efficient, or we create our own custom `_search_..` method. Task-6131693 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265059 Forward-Port-Of: odoo/odoo#260146
This update prevents Odoo from wasting time attempting to create API keys for unreachable databases. Previously, errors would clutter the synchronization results and cause delays. Now, the system skips these databases, streamlining the synchronization process and improving overall performance.
Original PR description
#### The aim of this commit is to: - avoid cluttering the user UI with "obvious" error. - avoid wasting up to 15s trying to create the key if we don't get any response. #### Context: When a db is unreachable, trying to create an api-key on it will result in an error. #### Before this commit: - The wizard showing the result of the synchronization would show the error for every single databases in which it encounters that error. If there are a lot, it would bloat the result. - An unresponsive db would waste 15s of our sync time in a synchronized process. If that happens multiple times, we could end up a lot of time waiting for no reason. #### After this commit: We don't try to create an api key for unreachable databases. task-id: [5945269](https://www.odoo.com/odoo/project.task/5945269) - follow up Forward-Port-Of: odoo/enterprise#117053
This update resolves a problem where the Brazil localization module (`l10n_br`) was incorrectly referencing a changed element in the address form. Upgrading to version 19.2 corrected the inheritance path, ensuring the Brazil module functions correctly with the updated address form. This prevents errors and maintains the proper display of address fields for Brazilian users.
Original PR description
Issue: ------ `l10n_br.address_form_fields` inherits from `portal.address_form_fields` but targets a `<select>` element that was moved to `portal_address_extended.address_extended_form_fields` in…
Issue: ------ `l10n_br.address_form_fields` inherits from `portal.address_form_fields` but targets a `<select>` element that was moved to `portal_address_extended.address_extended_form_fields` in [saas~19.2]. Traceback: ---------- ```py Error while parsing or validating view: Element '<xpath expr="//select[@name='city_id']/option[not(@value='')]">' cannot be located in parent view ``` Steps to reproduce: ------------------- 1. Install `l10n_br` in v19 2. Upgrade to v19.2 3. Upgrade the `l10n_br` module → Traceback Root cause: ----------- The view is adapting an element owned by a sibling view, making the inheritance hierarchy conceptually wrong and fragile. Solution: --------- Update the `inherit_id` of `l10n_br.address_form_fields` to `portal_address_extended.address_extended_form_fields` so it correctly inherits from the view that owns the targeted element. opw: [6125901] [saas~19.2]: https://github.com/odoo/odoo/commit/026c6f9f2a388ee509a135c53e38f5bb3d08ff73 [6125901]: https://www.odoo.com/odoo/70/tasks/6125901?debug=1 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where list view groups weren't displaying options correctly, mirroring the behavior of the underlying field widgets. The fix ensures that group values now accurately reflect the formatting options of the related widgets, improving data presentation and consistency within Odoo.
Original PR description
Before this commit, the values of groups in list view didn't get the options of the widget. Now, the groups extract the options of the column. The fact that the groups use the formatter of the widget now, show that there was an issue between the widget percentage and his formatter. The formatter, by default, show the trailing zero, but the widget, by default, doesn't. So, formatter has been fixed to be like the widget behavior. TASK-6226377 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an error that occurred when users removed the 'Source Entity Id Type' field in the Super Contributions reporting module. The fix ensures the system correctly handles this removal, preventing a data processing error and maintaining accurate reporting. This improves the stability of the Australian payroll functionality.
Original PR description
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an…
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an `Australian` company. - Go to `Payroll` > `Reporting` > `Australia` > `Super Contributions`. - Open an existing record or create a new one. - Remove the `Source Entity Id Type` value and click anywhere. `ValueError: Compute method failed to assign l10n_au.super.stream(<NewId origin=1>,).source_entity_id` After [change] in the selection field behavior, when the user removes the Source Entity Id Type, the compute method is triggered to compute the Source Entity ID. However, the condition in the compute method is not match, so no value is assigned. As a result, the method fails and raises an error. This commit ensures that if the condition is not match, the Source Entity ID is explicitly set to False. [1]- https://github.com/odoo/enterprise/blob/9d523d7aabffda277e1ef734caf2b0e434545dca/l10n_au_hr_payroll_account/models/l10n_au_super_stream.py#L61-L65 [change]: https://github.com/odoo/odoo/pull/214422/changes/8d2a42ac419fdf7943a0c11beb8c5de6c6f85bef Forward-Port-Of: odoo/enterprise#115466
This update corrects a usability issue in the composer feature of Odoo. Previously, adding text to a specific line above the signature delimiter could unintentionally hide text within the message. The fix moves the formatting element to prevent this confusing behavior, ensuring a cleaner and more predictable composer experience.
Original PR description
**Steps to reproduce:** - Go to the chatter of any record - Open the full composer - Empty line is present above the signature delimiter (`--`) - Adding text to this line will encapsulate it with the rest of the signature (and hide it by default in the message) **Issue:** Extra `<br>` was added to improve readability, but adding it this way (before the delimiter) can be confusing for the users as they can add text on what appears to be a normal empty line, that is actually hidden with the signature ellipsis. **Fix:** Moved the added `<br>` element outside the signature container for the full composer. The user can still find a way to modify the composer structure in a way that will hide part of the text (e.g. by typing just before the delimiter), but this limits the issue. related: https://github.com/odoo/odoo/commit/13a9c6f5010c3dee01aa0f66ed41b25f517a4a8c opw-6087042 Forward-Port-Of: odoo/odoo#257936
This update resolves an issue where archived sales teams were incorrectly appearing in the Sales Team dropdown when creating new opportunities. The fix removes a redundant setting that was causing this behavior, ensuring that only active sales teams are displayed. This improves the user experience and data accuracy within the CRM.
Original PR description
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and…
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and stage dropdowns. Creating an opportunity from the CRM app does not have this issue.
`res.partner.action_view_opportunity` sets `active_test: False` in the action context so archived opportunities show up in the list view. That context is passed down to the form opened from the action, and to every search the form runs to fill its dropdowns. So the dropdowns also return archived records.
The action's domain already has `('active', 'in', [True, False])`, which is enough to keep archived opportunities in the list on its own (the ORM only adds the "active = True" filter when `active` is not already in the domain). So we can just remove `active_test: False` from the context. This is what 18.0 was doing before https://github.com/odoo/odoo/commit/59feed9f26937ae8e2cab5cd7d2b6743ab6c0717 put the context flag back in.
The override in `website_crm_partner_assign` was setting `active_test: False` back on the action context for the same reason (so its extra search for assigned leads picks up archived ones). The flag is now applied locally on the `crm.lead` handle used for those searches, so archived leads are still found without polluting the action's context.
Steps to reproduce:
1. Archive a Sales Team in CRM > Configuration > Sales Teams
2. Open the Contacts app and pick any contact
3. Click the Opportunities smart button
4. Click "New" and open the Sales Team dropdown
=> Archived teams appear in the dropdown
Ticket [link](https://www.odoo.com/odoo/project.task/6134801)
opw-6134801
Forward-Port-Of: odoo/odoo#263283
Forward-Port-Of: odoo/odoo#261300This update fixes a regression where the color picker in Odoo was failing to recognize colors defined using the `color()` function. Following a recent website update, this change restores the color picker's ability to correctly handle these color definitions, ensuring consistent styling within the application. This resolves an issue impacting visual customization.
Original PR description
Following the website refactoring (commit 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2) `BuilderColorPicker` no longer recognizes colors defined using `color()`, introducing a regression. This commit restores support for `color()` values. Steps to reproduce: 1. Add the snippet `s_text_image`. 2. Manually, in the DOM, set the style of the first column to "background-color: color(srgb 0.4 0.2 0.8 / 0.4);". 3. In edit mode, click on the column to observe that the colorpicker does not recognize the background color. The same behavior can also be observed in the custom tab. Task: [5453922](https://www.odoo.com/odoo/project/974/tasks/5453922) Forward-Port-Of: odoo/odoo#265005 Forward-Port-Of: odoo/odoo#255331
This update fixes an issue where returned subcontracted products were incorrectly routed to the subcontractor's location instead of the user's stock. When returning products 'for exchange', the system now correctly directs returned items to the subcontractor's location and new incoming items to the user's stock, ensuring accurate inventory tracking. This prevents misallocation of stock and streamlines the subcontracting process.
Original PR description
## Issue When making a request for quotation for a subcontracted product and returning the delivery "for exchange", the new incoming delivery does not have the correct destination. Instead of having…
## Issue
When making a request for quotation for a subcontracted product and returning the delivery "for exchange", the new incoming delivery does not have the correct destination. Instead of having the stock of the user, the destination of the new incoming delivery is the same as its source: the subcontracting location.
<img width="1254" height="257" alt="5479900" src="https://github.com/user-attachments/assets/c7e6d392-8328-4a03-a71e-466e768f448b" />
## Steps to reproduce
1. Install MRP Subcontracting (`mrp_subcontracting`) and Purchase (`purchase`)
2. In Settings, enable *Subcontracting*
3. Create a Product P and a subcontracting BoM with Subcontractor S
4. Create a Request for Quotation
- Vendor: Subcontractor S
- Product: Product P (any quantity > 0)
5. Confirm the RFQ, receive the PO, validate the picking
6. On the validated picking, click *Return*, set the quantity of products to return, and click *Return for Exchange*
- This creates two new pickings, one to return the product(s) we received, and one to receive new products
7. Validate the two new pickings
8. **In Inventory > Reporting > Moves History, the very last `stock.move.line` has the same location in the *From* (`location_id`) and the *To* (`location_dest_id`) columns**
## Cause
The `location_dest_id` of the new `stock.move` is updated in `StockReturnPickingLine._prepare_move_default_values`.
https://github.com/odoo/odoo/blob/fb534f1eadcb8ef74e2ee6fd5b68872dddb978e3/addons/mrp_subcontracting/wizard/stock_picking_return.py#L20-L25
The condition added by https://github.com/odoo/odoo/commit/5404b426aac9 sets the destination of all returned subcontracted moves to the subcontractor location. This is incorrect when using "return for exchange", as in this case, the return move is directed towards the user's stock. In fact, when using "return for exchange", the following pickings are created:
| id | name | return_id | |
|:--:|--------------|:---------:|---|
| 1 | WH/IN/00001 | | Initial RFQ delivery |
| 2 | WH/OUT/00001 | 1 | Return of the initial RFQ delivery |
| 3 | WH/IN/00002 | 2 | New products delivery to replace the initial delivery. The stock.move.line of this stock.picking has a wrong `location_dest_id` |
## Fix
In the context of return for exchanges, the returned item must be directed to the *Subcontracting Location* while the new item must be directed to the *Stock*. In the `_prepare_move_default_values`, we should only set the `location_dest_it` to the subcontractor location for outgoing pickings.
opw-5479900
Forward-Port-Of: odoo/odoo#265071
Forward-Port-Of: odoo/odoo#245905This update addresses a technical error that prevented users from interacting with the 'Test' button within the IoT driver application. The issue stemmed from a data processing error, specifically an 'index out of range' error, which was preventing the button from functioning correctly. This fix ensures the 'Test' button is reliably available for users.
Original PR description
This PR fixes the following traceback when using "Test" button in the iot app: ``` 2026-05-18 07:48:36,248 22727 ERROR ? websocket: error from callback <bound method WebsocketClient.on_message of <WebsocketClient(Thread-6, started daemon 3995071456)>>: list index out of range 2026-05-18 07:48:36,249 22727 ERROR ? odoo.addons.iot_drivers.websocket_client: websocket received an error: list index out of range ``` opw-6226014 Forward-Port-Of: odoo/odoo#264897
This update fixes a limitation in the sale commission report that previously restricted the range of AML IDs it could process. Removing an unnecessary bit shift significantly expands the system's capacity to handle larger data sets, improving report performance. This change ensures the report can accurately process a wider range of sales commission data.
Original PR description
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs.…
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id <<10` This shifts the max aml.id 40 bits to the left. Example: Let's say MAX(aml.id) = 1; we will set the other variables to 1, as they often have little impact on the total size of the number. 1 << 20 = 1048576 1048576 | 1 = 1048577 1048577 << 10 = 1099512676352 1099512676352 | 1 = 1099512676353 1099512676353 << 10 = 1152922604119523328 With this format, the highest guaranteed AML ID this query can handle is under 838,861. The last 10-bit shift is unnecessary and increases the result. If we remove the last shift, the AMD ID this query can handle becomes much higher. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id` | | AML Max | RULES.ID Max |RULES.USER_ID Max| | --------------------- | ------ | ------ | ------ | | Before | 838,861 | 1,048,576 | 1,024 | | After | 858,993,459 |1,048,576 | 1,024| opw-6124026 Forward-Port-Of: odoo/enterprise#114711
Features or functions removed from Odoo
This update removes a potential risk for our IoT devices. Previously, they could inadvertently check out the main development branch (master), which is unstable. This change ensures IoT boxes always use a stable version, improving system reliability and security.
Original PR description
This PR removes a possibility for an iot box to ever checkout master. Since the latest stable version policy checking out to master is never used and is dangerous Forward-Port-Of: odoo/odoo#265186
22 changes
Enhancements to existing features
This update streamlines the invoicing process by automatically reconciling invoices created from sales orders. Previously, this required manual steps; now, the system directly links invoices to sales orders, improving efficiency and reducing potential errors. This change enhances the accuracy of financial reporting and simplifies reconciliation workflows.
Original PR description
This commit will allow to automatically reconcile the invoice create from the sale order by passing a context key that will be used in the create_invoices function. task-5502964 Forward-Port-Of: odoo/enterprise#108546
Resolved issues and error corrections
This update resolves an issue where Croatian invoices with alphanumeric characters in the business premises label (e.g., 'v1') were causing system errors. The fix modifies a key parsing rule to correctly recognize these labels, ensuring invoices are processed without errors. This improves the reliability of invoice generation for Croatian businesses.
Original PR description
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's…
### Description of the issue/feature this PR addresses: The business premises label on Croatian invoices can legitimately contain alphanumeric characters (e.g., "v1"), as noted in the field's tooltip. However, the regex pattern inside `_get_l10n_hr_fiscalization_number` used to extract the sequence parts strictly expected digits (`\d+`) for the premises label segment. Because of this, if an invoice was generated with an alphanumeric sequence like `INV-2026-0001/v1/1`, the regex failed to match and returned `False`, leading to a traceback when the system attempted to process the fiscalization number. This commit updates the regex to correctly accept alphanumeric characters for the premises label, ensuring the sequence parses successfully. opw-6129009 ### Steps to reproduce: - Settings > Users & Companies > Companies > New > set Address country to Croatia - Select the newly created Croatian company - Apps > Activate l10n_hr_edi module - Accounting > Configuration > Accounting > Journals > click Sales journal > change “Business premises label” to “v1” - Contacts > New > set Address country to Croatia - Accounting > Customers > Invoices > New > select the newly created contact and choose any product > Confirm ### Current behavior before PR: Traceback error when attempting to confirm an invoice when both the company and the customer have their country code set to 'HR'. This is because `_get_l10n_hr_fiscalization_number` does not accept alphabet characters in the premises label section of the regex. ### Desired behavior after PR is merged: - No traceback error when confirming the invoice - `_get_l10n_hr_fiscalization_number` correctly parses the fiscalization number Forward-Port-Of: odoo/odoo#263650
This update resolves an issue where clicking on archived users in channel or group member lists caused errors. By preventing these users from being clickable, we align the behavior with other parts of the system and eliminate the technical problem. This improves the user experience and ensures stability.
Original PR description
Previously, clicking on an archived user from the channel or group member list triggered a traceback. This PR prevents archived users from being clickable, aligning the behavior with the message model where the popover is not opened for archived users, thus avoiding the traceback. enterprise: https://github.com/odoo/enterprise/pull/117480 task-6179486 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264949 Forward-Port-Of: odoo/odoo#262247
This update resolves a test failure in the Odoo WhatsApp app's discuss sidebar. The change ensures the test accurately reflects the new system behavior of only considering active users when determining available commands. This improves the reliability of the test and ensures the app functions correctly for users.
Original PR description
This PR updates the discuss sidebar testcase to match the new behavior where only active users are considered when computing main_user_id, reducing the number of available commands and fixing the failing assertion. community: https://github.com/odoo/odoo/pull/262247 task-6179486 Forward-Port-Of: odoo/enterprise#117579 Forward-Port-Of: odoo/enterprise#117480
This update corrects a bug where users couldn't edit dates within the blog translate mode. The fix ensures the `DateTimeFieldPlugin` is correctly included in Odoo's core components, allowing for proper date field editing and preventing potential save errors. This improves the user experience for content creators.
Original PR description
The plugin `DateTimeFieldPlugin` was only added in registry `builder-plugins`. But it should also be included in the lists `CORE_PLUGINS` of `html_builder` and `TRANSLATION_PLUGINS` of `website` (the same as `MonetaryFieldPlugin` and similar plugins) Steps to reproduce: - Open `/blog` in translate mode - Click on a date - Bug: you can edit the text (and it will likely cause an error on save) task-6226376 Forward-Port-Of: odoo/odoo#264943
This update prevents the system from wasting time attempting to create API keys for unreachable databases. Previously, errors would clutter the synchronization results and cause delays. Now, the system skips these databases, improving synchronization speed and reducing unnecessary processing time.
Original PR description
#### The aim of this commit is to: - avoid cluttering the user UI with "obvious" error. - avoid wasting up to 15s trying to create the key if we don't get any response. #### Context: When a db is unreachable, trying to create an api-key on it will result in an error. #### Before this commit: - The wizard showing the result of the synchronization would show the error for every single databases in which it encounters that error. If there are a lot, it would bloat the result. - An unresponsive db would waste 15s of our sync time in a synchronized process. If that happens multiple times, we could end up a lot of time waiting for no reason. #### After this commit: We don't try to create an api key for unreachable databases. task-id: [5945269](https://www.odoo.com/odoo/project.task/5945269) - follow up Forward-Port-Of: odoo/enterprise#117053
This update resolves an error that occurred when users removed the 'Source Entity Id Type' setting in the Super Contributions module. The fix ensures the system correctly handles this removal, preventing a data processing failure and maintaining accurate reporting. This improves the stability of the Australian payroll reporting.
Original PR description
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an…
Currently an error occurs when the user removes the Source Entity Id Type on Super Contributions. **Steps to Reproduce:** - Install `l10n_au_hr_payroll_account` with demo data. - Switch to an `Australian` company. - Go to `Payroll` > `Reporting` > `Australia` > `Super Contributions`. - Open an existing record or create a new one. - Remove the `Source Entity Id Type` value and click anywhere. `ValueError: Compute method failed to assign l10n_au.super.stream(<NewId origin=1>,).source_entity_id` After [change] in the selection field behavior, when the user removes the Source Entity Id Type, the compute method is triggered to compute the Source Entity ID. However, the condition in the compute method is not match, so no value is assigned. As a result, the method fails and raises an error. This commit ensures that if the condition is not match, the Source Entity ID is explicitly set to False. [1]- https://github.com/odoo/enterprise/blob/9d523d7aabffda277e1ef734caf2b0e434545dca/l10n_au_hr_payroll_account/models/l10n_au_super_stream.py#L61-L65 [change]: https://github.com/odoo/odoo/pull/214422/changes/8d2a42ac419fdf7943a0c11beb8c5de6c6f85bef Forward-Port-Of: odoo/enterprise#115466
This update resolves a visual issue in the composer where adding text to a seemingly empty line would unintentionally hide the user's signature. The fix moves the formatting code to ensure consistent signature display, preventing user confusion and improving the overall composer experience. This change focuses on clarity and usability.
Original PR description
**Steps to reproduce:** - Go to the chatter of any record - Open the full composer - Empty line is present above the signature delimiter (`--`) - Adding text to this line will encapsulate it with the rest of the signature (and hide it by default in the message) **Issue:** Extra `<br>` was added to improve readability, but adding it this way (before the delimiter) can be confusing for the users as they can add text on what appears to be a normal empty line, that is actually hidden with the signature ellipsis. **Fix:** Moved the added `<br>` element outside the signature container for the full composer. The user can still find a way to modify the composer structure in a way that will hide part of the text (e.g. by typing just before the delimiter), but this limits the issue. related: https://github.com/odoo/odoo/commit/13a9c6f5010c3dee01aa0f66ed41b25f517a4a8c opw-6087042 Forward-Port-Of: odoo/odoo#257936
This update fixes a potential error message that could appear when spreadsheets are unavailable. The change prevents this traceback by handling server errors directly within the spreadsheet action, eliminating the need for complex template modifications. This improves the user experience and stability of the Enterprise edition.
Original PR description
The fix suggested in #81276 did not account for other spreadsheet models than a document as it required some modification in the component template. The same logic should then have been forwarded to other models (quality.check for instance] but that process is error prone. This revision changes the approach by handling the server error inside the abstract action so that no template modification is required. task-6208222 Forward-Port-Of: odoo/enterprise#117221
This update resolves an issue where archived sales teams were incorrectly appearing in the Sales Team dropdown when creating new opportunities. The fix removes a redundant setting that was causing this behavior, ensuring that dropdowns only display active teams. This improves the user experience and data accuracy within the CRM.
Original PR description
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and…
When you open a contact, click the Opportunities smart button, then click New and open the Sales Team dropdown, archived sales teams show up in the list. The same thing happens for the user, tags and stage dropdowns. Creating an opportunity from the CRM app does not have this issue.
`res.partner.action_view_opportunity` sets `active_test: False` in the action context so archived opportunities show up in the list view. That context is passed down to the form opened from the action, and to every search the form runs to fill its dropdowns. So the dropdowns also return archived records.
The action's domain already has `('active', 'in', [True, False])`, which is enough to keep archived opportunities in the list on its own (the ORM only adds the "active = True" filter when `active` is not already in the domain). So we can just remove `active_test: False` from the context. This is what 18.0 was doing before https://github.com/odoo/odoo/commit/59feed9f26937ae8e2cab5cd7d2b6743ab6c0717 put the context flag back in.
The override in `website_crm_partner_assign` was setting `active_test: False` back on the action context for the same reason (so its extra search for assigned leads picks up archived ones). The flag is now applied locally on the `crm.lead` handle used for those searches, so archived leads are still found without polluting the action's context.
Steps to reproduce:
1. Archive a Sales Team in CRM > Configuration > Sales Teams
2. Open the Contacts app and pick any contact
3. Click the Opportunities smart button
4. Click "New" and open the Sales Team dropdown
=> Archived teams appear in the dropdown
Ticket [link](https://www.odoo.com/odoo/project.task/6134801)
opw-6134801
Forward-Port-Of: odoo/odoo#263283
Forward-Port-Of: odoo/odoo#261300This update fixes an error in the Austrian localization module that incorrectly used a fixed 15-day rule for VAT and EC sales list reporting deadlines. The fix now accurately reflects the official Austrian filing deadlines, ensuring compliance and preventing potential penalties. This improves the accuracy of financial reporting for Austrian businesses using Odoo Enterprise.
Original PR description
**[FIX] l10n_at_reports: correct Austrian return deadlines** The Austrian localization used a fixed `15 days` rule for both VAT returns and EC sales lists. This does not match the filing deadlines: the VAT return is due on the 15th day of the second following month while the EC sales list is due by the end of the following month (sources below). This fix replaces the hardcoded day offset with month-based deadline computation sources: https://www.usp.gv.at/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/umsaetze-mit-auslandsbezug/zusammenfassende-meldung-zm.html https://www.usp.gv.at/en/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/entstehen-der-steuerschuld-und-pflichten/umsatzsteuervoranmeldung.html opw-6147343 Forward-Port-Of: odoo/enterprise#116212
This update fixes an error that occurred when selecting shift templates on planning slots, preventing a system crash. The change ensures that if the calculation fails due to a long time range, the system reverts to a previously calculated end date, ensuring accurate planning.
Original PR description
Currently, an error occurs when a user selects a shift template on a planning slot. **Steps to Reproduce:** - Install the `Planning` module with demo data. - Create a `Resource Time Off` record with…
Currently, an error occurs when a user selects a shift template on a planning slot. **Steps to Reproduce:** - Install the `Planning` module with demo data. - Create a `Resource Time Off` record with `start` and `end date` separated by more than `1400 days (around 3.9 years)`, and Set the Working Hours field to Standard 40 hours/week. - Go to `Planning` > `Configuration` > `Shift Templates`, open an `existing record` or create a `new one`, and set the `Working Days` to more than 1 day. - Create a new `planning slot`, Assign the resource `Abigail Peterson`, and select the above `shift template`. `AttributeError: 'bool' object has no attribute 'replace'` This error occurs because when the user sets the shift template, the compute method runs to calculate the start and end datetimes [1]. It computes the end datetime by adding the template duration in working days from the given start datetime using the resource working calendar within a searchable range of around 1400 days [2]. During this computation, leaves and non-working days are skipped [3]. If no valid working interval is found within the searchable range, then it returns False [4], which raises the error [5]. This commit ensures that if plan_days returns False, the computation falls back to the previously calculated end date. [1]: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/planning/models/planning.py#L662-L671 [2]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L826-L835 [3]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L533-L537 [4]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L835 [5]- https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/planning/models/planning.py#L653-L654 sentry-7472958590 Forward-Port-Of: odoo/enterprise#117073
This update fixes an error in how VAT carryover reimbursements are calculated when claiming unclaimed tax amounts. The previous calculation incorrectly used data from the previous month's tax report, leading to inaccurate reimbursement move amounts. This ensures accurate VAT reporting and reimbursement processing.
Original PR description
When generating a VAT return with an unclaimed tax amount carried to the next month, the carryover reimbursement move amounts are computed with an incorrect ratio. Steps to reproduce: - Create and…
When generating a VAT return with an unclaimed tax amount carried to the next month, the carryover reimbursement move amounts are computed with an incorrect ratio. Steps to reproduce: - Create and post a bill in May containing a VAT amount. - Create and post a bill in June containing a VAT amount. - Create a VAT return for May to carry over the VAT amount to the next month. - Create a VAT return for June, requesting the full VAT amount to be reimbursed. - Validate and send the June VAT return. - Check the generated reimbursement move Issue: Line values does not correspond to anything real/tangible. It occurs because when computing the ratio for the move we check the last tax report entry, where we find the amount of tax from the past months and a line balancing the last month that should not be taken into account. The "Balance tax current account (receivable)" line from the tax closing entry is mistakenly picked up as a tax carried forward line, throwing off the amounts. opw-5961836 Forward-Port-Of: odoo/enterprise#116930 Forward-Port-Of: odoo/enterprise#115451
This update fixes an issue where newly created projects weren't automatically using the stage defined in their project template. The fix ensures that projects created from templates correctly inherit the intended stage, streamlining project setup and reducing manual adjustments. This improves consistency and efficiency in project management workflows.
Original PR description
Steps to reproduce: - 1. Enable "Project Stages" in Project settings. 2. Create a project template and move it to a stage other than the first one (e.g., "Stage 2"). 3. Create a project from this template (manually or via a Sales Order). Issue: - The newly created project is always placed in the first stage instead of inheriting the stage defined in the template. Cause: - The `stage_id` field on the `project.project` model is defined with `copy=False` When a project is created from a template, this field is excluded from the copied values, causing the new project to fall back to the default first stage. Fix: - Override `copy_data` to explicitly include `stage_id` from the source project template. task-6019852 Forward-Port-Of: odoo/odoo#264827 Forward-Port-Of: odoo/odoo#253864
This update addresses a technical issue that prevented users from consistently interacting with the 'Test' button within the IoT driver application. The fix corrects a data processing error (specifically, an 'index out of range' error) that was causing the button to malfunction. This ensures reliable operation of the IoT driver.
Original PR description
This PR fixes the following traceback when using "Test" button in the iot app: ``` 2026-05-18 07:48:36,248 22727 ERROR ? websocket: error from callback <bound method WebsocketClient.on_message of <WebsocketClient(Thread-6, started daemon 3995071456)>>: list index out of range 2026-05-18 07:48:36,249 22727 ERROR ? odoo.addons.iot_drivers.websocket_client: websocket received an error: list index out of range ``` opw-6226014 Forward-Port-Of: odoo/odoo#264897
This update fixes a limitation in the sale commission report's query, allowing it to handle significantly larger sales order IDs. By removing an unnecessary bit shift, the report now supports a much wider range of data, improving performance and scalability. This change ensures the report continues to function correctly with growing sales volumes.
Original PR description
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs.…
The combined query for sale.commission.achievement.report originally performs several bitwise shifts, starting with the max AML ID. This is done to create a composite number ID for the combined IDs. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id <<10` This shifts the max aml.id 40 bits to the left. Example: Let's say MAX(aml.id) = 1; we will set the other variables to 1, as they often have little impact on the total size of the number. 1 << 20 = 1048576 1048576 | 1 = 1048577 1048577 << 10 = 1099512676352 1099512676352 | 1 = 1099512676353 1099512676353 << 10 = 1152922604119523328 With this format, the highest guaranteed AML ID this query can handle is under 838,861. The last 10-bit shift is unnecessary and increases the result. If we remove the last shift, the AMD ID this query can handle becomes much higher. `MAX(aml.id)::bigint <<20) | max(rules.id)::bigint <<10 | rules.user_id` | | AML Max | RULES.ID Max |RULES.USER_ID Max| | --------------------- | ------ | ------ | ------ | | Before | 838,861 | 1,048,576 | 1,024 | | After | 858,993,459 |1,048,576 | 1,024| opw-6124026 Forward-Port-Of: odoo/enterprise#114711
This update fixes a minor visual issue in the multi-currency popover. Previously, the display would include an unnecessary "on" keyword when a date wasn't available, creating an awkward appearance. This change ensures a cleaner and more professional user experience for currency conversions.
Original PR description
This commit fixes a formatting issue in the multi-currency popover when no currency exchange rate is available. Previously, the popover would awkwardly display the word "on" with no trailing date (e.g., "CHF 22.81 at $ 1.00 on"). The template now conditionally hides the "on" keyword when no date is present to ensure a clean UI. task-6227557
The Odoo tour feature was experiencing a technical glitch that caused it to repeatedly refresh, slowing down the user experience. This fix prevents an infinite loop of rendering, ensuring the tour operates smoothly and efficiently. This improvement enhances the overall user experience.
Original PR description
Before this commit, the tour pointer entered an infinite loop of rendering because one change in its state triggered DOM mutations on which the tour listen to update the pointer, triggering the rendering of the pointer. This was because of a reactive's state being update too early. After this commit, the number of renderings is limited to a reasonable minimum. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an error in the project dashboard that was incorrectly displaying revenue figures due to a miscalculation of recurring subscription plans. The fix ensures that revenue is accurately reflected based on the selected yearly subscription, resolving discrepancies in reported income and invoices.
Original PR description
__ ## Short functional explanation of the error When checking the dashboard on a project we created with a yearly subscription, the values shown are incorrect. ## Reproduction Steps 1. Create a new…
__ ## Short functional explanation of the error When checking the dashboard on a project we created with a yearly subscription, the values shown are incorrect. ## Reproduction Steps 1. Create a new product. Check the Subscription field and set the Product type as Service. On the Create on Order field, set Project & Task. Then, in the Recurring Price tab, add a Monthly plan with price 50 and yearly plan with price 40. 2. Create a new Quotation. Set a customer and add the product you just created in an Order line. Set the Quantity to 100 and set the recurring plan as Yearly. You'll see the amount be at 4000, and the total amount at 4600 with taxes. Click on Confirm. 3. Create an invoice and confirm it. 4. Click on the Project smart button. Then, on the top right, click on the view menu > Top Menu. Select Dashboard and click on it. ### Expected behavior On the dashboard, we should see the Revenues under Profitability at 4000. To invoice should be left at 0 and Invoiced should be at 4000. Expected should be at 4000. ### Unexpected behavior On the dashboard, To Invoice is at 333, and Expected is at 4333. This corresponds to our invoice + 4000/12 -> monthly recurring plan, with the price of the yearly plan! ## Origin of the issue We always add the `recurring_monthly` value when showing the profitability, no matter the recurring plan: https://github.com/odoo/enterprise/blob/cdc0d5d57f6b27a6bb5e451d48bdbef4e3dde5cb/project_sale_subscription/models/project_project.py#L86 We should only add the `recurring_monthly` value for as many monthly subscriptions we have, not for *all* the subscriptions. __ opw-5916688 Forward-Port-Of: odoo/enterprise#113918
This update resolves an issue where unsent Italian fiscal receipts were incorrectly transmitted as refunds to the printer. The fix ensures that actual orders are printed correctly, preventing potential reporting errors and compliance issues related to Italian tax regulations. This improves the reliability of the POS system for Italian businesses.
Original PR description
Steps to reproduce: - Set up an Italian fiscal printer; - In the POS, process an order and simulate an unsent receipt (e.g., by disconnecting the device from the network); - Navigate to the "Orders" screen and select the unsent order; - Click "Print receipt" Issue: The order isn't properly loaded. Because there is no order line, it is considered as a refund and is transmitted to the fiscal printer with a "RETURN " header instead of the actual fiscal receipt. [opw-5270697](https://www.odoo.com/odoo/project.task/5270697) Forward-Port-Of: odoo/enterprise#117043
This update fixes a problem where adding rental products to the cart would fail due to mismatched date calculations. The fix ensures that rental product durations are correctly handled, regardless of whether they're priced by days or hours, preventing errors when adding items to the cart. This improves the overall rental experience for customers.
Original PR description
Steps to reproduce: =================== 1. Go to the shop page and use the rental date picker to select a start and end date with hours. 2. Find a rental product configured with "Days" pricing. 3.…
Steps to reproduce: =================== 1. Go to the shop page and use the rental date picker to select a start and end date with hours. 2. Find a rental product configured with "Days" pricing. 3. Add to card directly from the product card 4. Add a rental product from product image that has date type value date 5. Go to that product details page. 6. Click add to cart -> Invalid operation, You cannot mix different rental periods... Cause: ====== When adding a product from the shop list view, the system uses the default start/end dates (from the rental period) exactly as first added. However, the "Add to Cart" logic on the product details page attempts to adapt the selected dates to the product's specific rental unit (e.g., normalizing the time component for 'Day' pricing). This re-calculation creates a timestamp mismatch between the item already in the cart (from the shop view) and the new item being added (from the details page). Solution: ========= The add-to-cart flow has been updated to correctly utilize the default duration values (the globally selected dates) if they exist. opw-5450576 Forward-Port-Of: odoo/enterprise#103373
This update fixes an issue where project update descriptions incorrectly showed inflated budget totals after budget revisions. The fix ensures that only the active, confirmed budget revision is used, providing accurate budget information for project updates. This improves the reliability of project cost reporting.
Original PR description
**Problem:** When a project analytic budget is revised, the project update description shows an inflated total budget — the sum of both the original and the revised amounts — instead of reflecting…
**Problem:** When a project analytic budget is revised, the project update description shows an inflated total budget — the sum of both the original and the revised amounts — instead of reflecting only the active (confirmed) revision. **Steps to reproduce:** 1. Create a project with an analytic account 2. Create an analytic budget of $10,000 and confirm it 3. Create a revision of that budget for $15,000 and confirm it 4. Create a new project update 5. The update shows "$25,000" as the total budget instead of "$15,000" **Current behavior:** The project update displays the sum of all budget revisions ($25,000), regardless of their state. **Expected behavior:** Only the active confirmed budget ($15,000) should be used. **Cause of the issue:** `_compute_budget` queries all `budget.line` records matching the project's analytic account without filtering by the parent `budget.analytic` state. When a budget is revised, the original transitions to state `revised` while the new one becomes `confirmed`. Because `_compute_budget` has no state filter, it sums both, producing an inflated `total_budget_amount`. This field is then used in the project update template to compute the displayed budget total and percentage. By contrast, `_get_budget_items` — used for the detail rows — already applies `state in ['confirmed', 'done']`, so the two methods were inconsistent. **Fix:** Applying the same state filter to `_compute_budget` as already present in `_get_budget_items` ensures both methods draw from the same set of active budgets, keeping the project update totals consistent with the budget detail rows. opw-6128855 Forward-Port-Of: odoo/enterprise#117490 Forward-Port-Of: odoo/enterprise#115285
3 changes
Resolved issues and error corrections
This update fixes an issue where new WhatsApp channel members weren't correctly displayed as avatars in the sidebar. Now, avatars are pulled directly from the channel's WhatsApp member, ensuring users see the correct representation of each conversation. This improves the user experience and consistency within the WhatsApp channel.
Original PR description
WhatsApp sidebar avatars should be resolved from the channel's whatsapp member, not from an arbitrary non-self member. Before this fix, adding a member to a WhatsApp channel caused the default Discuss avatar to be displayed instead of the actual WhatsApp member's avatar. This happened because the correspondent was not correctly computed for channels of type whatsapp. task-[5879840](https://www.odoo.com/odoo/project/1519/tasks/5879840) Forward-Port-Of: odoo/enterprise#117633 Forward-Port-Of: odoo/enterprise#115745
This update fixes an error that occurred when selecting shift templates on planning slots, specifically when dealing with long periods of leave. The change ensures the system gracefully falls back to a previously calculated end date if the template duration cannot be accurately determined, preventing the application from crashing. This improves the reliability of shift planning.
Original PR description
Currently, an error occurs when a user selects a shift template on a planning slot. **Steps to Reproduce:** - Install the `Planning` module with demo data. - Create a `Resource Time Off` record with…
Currently, an error occurs when a user selects a shift template on a planning slot. **Steps to Reproduce:** - Install the `Planning` module with demo data. - Create a `Resource Time Off` record with `start` and `end date` separated by more than `1400 days (around 3.9 years)`, and Set the Working Hours field to Standard 40 hours/week. - Go to `Planning` > `Configuration` > `Shift Templates`, open an `existing record` or create a `new one`, and set the `Working Days` to more than 1 day. - Create a new `planning slot`, Assign the resource `Abigail Peterson`, and select the above `shift template`. `AttributeError: 'bool' object has no attribute 'replace'` This error occurs because when the user sets the shift template, the compute method runs to calculate the start and end datetimes [1]. It computes the end datetime by adding the template duration in working days from the given start datetime using the resource working calendar within a searchable range of around 1400 days [2]. During this computation, leaves and non-working days are skipped [3]. If no valid working interval is found within the searchable range, then it returns False [4], which raises the error [5]. This commit ensures that if plan_days returns False, the computation falls back to the previously calculated end date. [1]: https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/planning/models/planning.py#L662-L671 [2]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L826-L835 [3]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L533-L537 [4]: https://github.com/odoo/odoo/blob/a439bd305112f6efc752ce900f7782e7faaf7312/addons/resource/models/resource_calendar.py#L835 [5]- https://github.com/odoo/enterprise/blob/6ae5d3df6e9305416e4d6f74259cd01753025f42/planning/models/planning.py#L653-L654 sentry-7472958590 Forward-Port-Of: odoo/enterprise#117073
This update prevents the report editor in Odoo Studio from using default theme colors, which were causing potential styling conflicts. This change improves the consistency and reliability of report design within Studio, ensuring reports are rendered correctly regardless of the underlying interface customizations. This resolves a longstanding architectural issue.
Original PR description
Before this commit, there was no way to tell the ColorPicker to not use the DEFAULT_THEME_COLOR_VARS (ie classes of the form o-color-[n] with n some integer) Those colors are a bit special (see full…
Before this commit, there was no way to tell the ColorPicker to not use the DEFAULT_THEME_COLOR_VARS (ie classes of the form o-color-[n] with n some integer)
Those colors are a bit special (see full discussion on the opw)
Their existence is described in module web
Their CSS definition is implemented in module html_editor
Reports don't use them at all We probably don't want reports' style
to be influenced by the presence or lack thereof of the html_editor
module, which was originally made to customize the interface.
Those architecture issues should be solved downstream in master, but they are practically endemic in Odoo.
This commit addresses the fact that Studio's report editor should not allow those colors as possible customization by offering the components and plugins in the chain a props to disable them.
After this commit (and more broadly the PR bundle), the default theme colors are not available in studio's report editor.
see odoo/odoo#251446
backport of https://github.com/odoo/enterprise/pull/109206
opw-6167143
community: https://github.com/odoo/odoo/pull/264917
Forward-Port-Of: odoo/enterprise#117634
Forward-Port-Of: odoo/enterprise#1175552 changes
Resolved issues and error corrections
This update resolves an issue where UBL invoices would fail to import due to extra spaces in the 'EndpointID' field. The change automatically removes these spaces, ensuring invoices are correctly processed and imported, improving data accuracy.
Original PR description
**PROBLEM** When importing a ubl that, for some reason, have trailing space on the text of the EndpointID node, we refuse it. This PR strips the trailing spaces on the import. **STEP TO REPRODUCE** 1. Import a ubl as a bill, with a trailing space in the EndpointID of the other party. 2. Notice the import fail, with the error: The Peppol endpoint (50238597645 ) is not valid. It should contain only letters and digit. opw-6227395
This update ensures that event tickets are correctly created when selling event tickets through the POS system while offline. Previously, a page reload would cause the system to lose the ticket information. Now, the system retains event registration details until the order is fully synced with the server, guaranteeing accurate ticket generation.
Original PR description
When selling event tickets in POS while offline, the order could be synced later but without creating event registrations (tickets) after a page reload. Steps to reproduce: ------------------- * Open…
When selling event tickets in POS while offline, the order could be synced later but without creating event registrations (tickets) after a page reload. Steps to reproduce: ------------------- * Open a POS session with `pos_event` * Sell an event ticket * Switch to offline mode * Validate payment while offline (order becomes paid but unsynced) * Reload/close and reopen POS, then reconnect * Let the order sync > Observation: The `pos.order` is created on the backend, but `event.registration` and `event.registration.answer` are missing so tickets are not generated. Why the fix: ------------ `pos_event` used `order.finalized` as IndexedDB cleanup condition for `event.registration` and `event.registration.answer`. For paid-but-unsynced orders, `finalized` is already true, so those records can be removed from IndexedDB too early. After reload, the order is restored/synced but without its event registration payload. Implementation: --------------- Use `order.canBeRemovedFromIndexedDB` instead of `order.finalized` for `event.registration` and `event.registration.answer` retention rules, so records are kept locally until the order is truly synced (server id assigned) or canceled. Test Note: --------------- Use case is hard to simulate exactly. Add a basic unit test to assert both registration models are kept for paid unsynced orders and only removable once synced. opw-6056079 Forward-Port-Of: odoo/odoo#263912 Forward-Port-Of: odoo/odoo#256615
5 changes
Enhancements to existing features
This update modernizes the web studio report editor's user interface, aligning it more closely with the company's website design. The changes include a reorganized layout with separate tabs for content editing, improved navigation, and a simplified sidebar for options and resources, enhancing the report creation experience.
Original PR description
This commit reworks the web_studio report editor UI layout and style to be more inline with the website editor. - Wysiwyg/Xml/Preview are now separate tabs - Save/Discard and Undo/Redo are in the sidebar - Options are now in groups in the sidebar - Resources are now in the sidebar as well instead of the hierarchical select Community: https://github.com/odoo/odoo/pull/242868 Task: [5150355](https://www.odoo.com/odoo/project/133/tasks/5150355)
This update simplifies the order signing process by hiding the 'Sign Now' button when an order is already in the signing workflow. This reduces confusion for users and streamlines the process, ensuring they only see the relevant options at each stage. It's a minor improvement focused on user experience.
Original PR description
task-5344686
This update allows users to easily reorder signers directly within the template sidebar using 'Move Up' and 'Move Down' options. This simplifies the process of managing signing orders and ensures the correct sequence of signers is displayed, improving workflow efficiency.
Original PR description
Adds Move Up / Move Down options to the signer's three-dot menu, letting users adjust the signing order directly from the template sidebar. task-6231529
This update introduces dashboard warnings related to payroll, mirroring the existing alerts for employee and payslip issues. This enhancement ensures users receive timely notifications about potential discrepancies or errors within the payroll system, improving accuracy and compliance.
Original PR description
In this commit, we created dashboard warnings based on existing employee + payslip's issues. task-5387328
Resolved issues and error corrections
This update adjusts the default date range for the Lead and Pipeline dashboards to 'Last 30 days'. This change provides users with a more relevant and current view of their sales data, making it easier to analyze recent performance and trends. It resolves a previous issue where the default date range was not consistently set.
Original PR description
This commmit fixes the date filter default value to `Last 30 days`. Task: 5902231 Forward-Port-Of: odoo/enterprise#114560
7 changes
Enhancements to existing features
This update optimizes how bank statement details are recorded within Odoo. By using a batch logging function, the system now processes transactions more efficiently, reducing delays and improving overall performance. This change focuses on internal system improvements, enhancing the speed and reliability of bank statement management.
Original PR description
There is no need for a full message post to get the details of the transaction. We can use the batched function instead `_message_log_batch`.
Resolved issues and error corrections
This update fixes an error in the Luxembourg Annual VAT Declaration report that resulted in incorrect calculations for Appendix E 1a. The fix ensures that key financial data is included accurately, resolving a discrepancy in the reported VAT totals. This improves the reliability of the report for Luxembourg businesses.
Original PR description
### Issue: The formula `L10N_LU_TAX_163` in the Luxembourg Annual VAT Declaration was incorrect: - `L10N_LU_TAX_791.year_start` was added twice - `L10N_LU_TAX_993.year_start` was missing As a result, the computed total in Appendix E 1a was incorrect ### Steps to reproduce: - Install `l10n_lu_reports` - Open the `Report: Annual VAT Declaration (LU)` - Go to `Appendix E` - Use the `Start of Financial year` pencil icons to manually set values for fields `791` and `993` - Check the computed value of field `163` After the fix, both values are included exactly once in the formula opw-6158950 Forward-Port-Of: odoo/enterprise#117214
This update prevents the report editor in Odoo Studio from using default theme colors, which were causing potential styling conflicts. This change improves the consistency and reliability of report design within Studio, ensuring reports are rendered correctly regardless of the underlying interface customizations.
Original PR description
Before this commit, there was no way to tell the ColorPicker to not use the DEFAULT_THEME_COLOR_VARS (ie classes of the form o-color-[n] with n some integer) Those colors are a bit special (see full…
Before this commit, there was no way to tell the ColorPicker to not use the DEFAULT_THEME_COLOR_VARS (ie classes of the form o-color-[n] with n some integer)
Those colors are a bit special (see full discussion on the opw)
Their existence is described in module web
Their CSS definition is implemented in module html_editor
Reports don't use them at all We probably don't want reports' style
to be influenced by the presence or lack thereof of the html_editor
module, which was originally made to customize the interface.
Those architecture issues should be solved downstream in master, but they are practically endemic in Odoo.
This commit addresses the fact that Studio's report editor should not allow those colors as possible customization by offering the components and plugins in the chain a props to disable them.
After this commit (and more broadly the PR bundle), the default theme colors are not available in studio's report editor.
see odoo/odoo#251446
backport of https://github.com/odoo/enterprise/pull/109206
opw-6167143
community: https://github.com/odoo/odoo/pull/264917
Forward-Port-Of: odoo/enterprise#117780
Forward-Port-Of: odoo/enterprise#117555This update fixes an issue where freight charges were incorrectly applied to all pickings, particularly with backorders. The change ensures freight costs are only included in the initial picking, aligning with how delivery costs should be invoiced to customers and accounting for potential changes in delivery costs.
Original PR description
Commit 28b840b introduced logic to include `freight_costs` in the customs document generated bySendcloud. It introduced 2 new issues as a result: 1. When creating backorders, the `freight_costs` are…
Commit 28b840b introduced logic to include `freight_costs` in the customs document generated bySendcloud. It introduced 2 new issues as a result: 1. When creating backorders, the `freight_costs` are not divided but instead propagated to all of the pickings. 2. When there is no SO, we were taking the total value of all delivered goods, which doesn't make much sense considering the `freight_costs` field should be the cost of the delivery itself. Solution ----- For the first problem, there are a couple things to keep in mind: - the total `freight_costs` declared to the customs entity should be the amount invoiced to the customer - products can be added and removed from the picking after the SO has been confirmed - actual delivery cost can change between invoice date and actual delivery date - picking can be split into multiple packages at the user's discretion Considering all of the above, we will simply forward the invoiced amount with the first confirmed picking and none of the backorders. ----- Ticket: opw-6013387 Forward-Port-Of: odoo/enterprise#117115 Forward-Port-Of: odoo/enterprise#111304
This update fixes an issue where WhatsApp channel avatars were incorrectly displayed as the default Discuss avatar after a member was added. Now, avatars are correctly pulled from the channel's WhatsApp member, ensuring accurate representation and a better user experience for WhatsApp channel communication. This improves the visual consistency and usability of the WhatsApp feature.
Original PR description
WhatsApp sidebar avatars should be resolved from the channel's whatsapp member, not from an arbitrary non-self member. Before this fix, adding a member to a WhatsApp channel caused the default Discuss avatar to be displayed instead of the actual WhatsApp member's avatar. This happened because the correspondent was not correctly computed for channels of type whatsapp. task-[5879840](https://www.odoo.com/odoo/project/1519/tasks/5879840) Forward-Port-Of: odoo/enterprise#117633 Forward-Port-Of: odoo/enterprise#115745
This update resolves an issue where unsent Italian fiscal receipts were incorrectly transmitted as refunds to the printer. The fix ensures that actual orders are printed with the correct fiscal receipt data, preventing reporting errors and ensuring compliance. This improves the accuracy of sales records for Italian POS operations.
Original PR description
Steps to reproduce: - Set up an Italian fiscal printer; - In the POS, process an order and simulate an unsent receipt (e.g., by disconnecting the device from the network); - Navigate to the "Orders" screen and select the unsent order; - Click "Print receipt" Issue: The order isn't properly loaded. Because there is no order line, it is considered as a refund and is transmitted to the fiscal printer with a "RETURN " header instead of the actual fiscal receipt. [opw-5270697](https://www.odoo.com/odoo/project.task/5270697) Forward-Port-Of: odoo/enterprise#117043
This update fixes a discrepancy in how contract types are defined within Odoo's HR modules. Specifically, the definition of `contract_type_id` was standardized across the base and Belgium-specific versions. This ensures consistent data and avoids potential errors in reporting and calculations related to employee contracts.
Original PR description
[IMP] hr_contract_salary: fix contract_type_id definition The definitions of the contract_type_id in hr_contract_salary_offer and l10n_be_hr_contract_salary/hr_contract_salary_offer should be same I converted the definition of contract_type_id in the base module to the Belgium one. Also, the contract_type_id was inserted to the view in Belgium one as well, I deleted that part to prevent double appearance. This task is only for v.17, after this version I will open a new PR to handle them. Do not forward the task after v.17 (only for v.17) task - 6101717 Forward-Port-Of: odoo/enterprise#117586 Forward-Port-Of: odoo/enterprise#113244
10 changes
Resolved issues and error corrections
This update fixes an issue where refreshing a timesheet record from the 'My Timesheets' grid view incorrectly displayed the generic 'Analytic Items' form. The fix ensures the correct timesheet-specific form view is consistently shown after a page refresh, providing a more accurate and user-friendly experience.
Original PR description
**Problem** When opening a timesheet record from the *My Timesheets* grid view (via the magnifier icon that appears on cell hover) and refreshing the page, the wrong form view is loaded: the generic…
**Problem** When opening a timesheet record from the *My Timesheets* grid view (via the magnifier icon that appears on cell hover) and refreshing the page, the wrong form view is loaded: the generic "Analytic Items" form on `account.analytic.line` instead of the timesheet-specific form. **Steps to reproduce** 1. Go to *Timesheets* → *My Timesheets* → switch to **Grid** view. 2. Hover a cell with a timesheet entry and click the magnifier (search) icon. 3. The list opens; click a record to open its form view. 4. Observe the URL: `/odoo/timesheets/<id>`. 5. Refresh the page (F5). **Expected** The same timesheet form view is shown after refresh. **Actual** The "Analytic Items" form view (`analytic.view_account_analytic_line_form`) is shown instead, exposing the wrong layout/fields. **Cause** The grid renderer's `openRecords` builds an inline `ir.actions.act_window` with no `path` and no `id`. When the page is refreshed, the action service reconstructs the action from the URL state alone — model + resId — and resolves the form view by priority. Two priority-1 form views exist on `account.analytic.line` (`analytic.view_account_analytic_line_form` and `hr_timesheet.hr_timesheet_line_form`); the lower-id one wins, which is the analytic one. **Fix** Override `openRecords` in `TimesheetGridRenderer` to carry the current action's `path` (or `id`, for non-pathed database actions) onto the inline action. The URL then stays anchored to the original act_window (e.g. `/odoo/timesheets/<id>`), and on refresh the action service rebuilds it with the correct views, including the timesheet-specific form. opw-6133602
This update resolves a bug where the Gantt view incorrectly displayed working hours on public holiday dates for flexible employees. The fix converts all time zone calculations to UTC, ensuring accurate holiday scheduling and preventing employees from being marked as available during holiday periods. This improves the accuracy of employee availability tracking.
Original PR description
[FIX] hr_attendance_gantt: fix gantt view with public holidays Bug reproduction: 1 - Select flex schedule employee (or change its schedule to 40h flex one) and make its contract before 01/01/2026 2 -…
[FIX] hr_attendance_gantt: fix gantt view with public holidays
Bug reproduction:
1 - Select flex schedule employee (or change its schedule to 40h flex one) and make its contract before 01/01/2026
2 - Create a new public holiday on 01/01/2026 (from 00.00 to 23.59 or 23.55 (depends on version, it does not matter))
3 - in attendance app the cell from 00.00 to 01.00 seems white for that day and for selected employee (this cell seems like not holiday and employee can work)
Bug cause:
1 - After a long traceback, _gantt_unavailability in hr_attendance_gantt/HrAttendance, if an employee is flexible then unavailable_intervals is calculated with the Brussel time zone
2 - All other unavailable intervals are converted to the UTC in the function of _gantt_unavailability except in the final lines of the function.
3 - When the employee is flexible and since the conversion is not done in the final lines, it remains 1 hour more (UTC+1), it is from 1 am to 1 am of next day instead of 0 am to 23.59.
Bug solution:
1 - I converted the timezone to UTC to solve the problem.
task - 6067070This update corrects a formatting error in invoices where extra decimal places were being added to the displayed price. The fix reduces the precision calculations to prevent these unnecessary digits from appearing in the PDF output, ensuring invoices display correctly.
Original PR description
Issue: - Create an invoice with a line having a price of `528,000,000.00` - Print the invoice -> pdf displays `528,000,000.000001` Cause: In `value_to_html` from `ir.qweb.field.float`, we compute the maximum precision that we can get from the value, to avoid parasite digits. The maximum is 15, so if a number has 11 digits, we won't ask for a precision higher than 4. But in `float_round`, they multiple the value with its precision, then add `epsilon` (a small value). So we're now working with a 16 digits float, which is what we want to avoid. Solution: Reduce the maximum precision from one digit before calling `float_round`. opw-6012129
A recent update inadvertently removed a key test related to product margins. This change has been corrected to ensure continued testing and maintain the quality of the product margin calculations. Restoring this test helps guarantee the accuracy and reliability of our product margin features.
Original PR description
Commit e61403f5a3 accidentally removed test_aggregates while resolving a forward-port conflict. Restoring the test to maintain coverage. no task-id
This update resolves a crash during KSeF (Polish e-tax) certificate authentication for foreign certificates. The fix intelligently determines the certificate type, handling variations in the certificate data to ensure successful authentication and avoid errors. This improves the reliability of the Odoo system when processing KSeF transactions.
Original PR description
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400…
### Description of the issue/feature this PR addresses: **Issue**: During KSeF authentication, some foreign qualified certificates causes a crash with error _"Failed to authenticate with XAdES: 400 Client Error: Bad Request for url: https://api.ksef.mf.gov.pl/v2/auth/xades-signature"_ This is due to Odoo not handling different `SubjectIdentifierType` **Solution**: Implement a try/except block to safely check for the NIP in the certificate's subject string, defaulting the identifier type to `certificateFingerprint` when the NIP is missing or a ValueError is caught. ### Current behavior before PR: The `SubjectIdentifierType` is hardcoded as `certificateSubject`, and does not handle `certificateFingerprint` at all. This causes there to be an error when trying to authenticate with the KSeF server using XAdES signature. ### Desired behavior after PR is merged: The sign_authentication_challenge method will now safely evaluate the subject string. It assigns `certificateSubject` only if the NIP is verified to be in the subject string. If the NIP is absent or a ValueError occurs during parsing, the system safely falls back to using `certificateFingerprint`. This prevents tracebacks and ensures the correct XML payload is sent to the KSeF server. opw-6125243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects an issue where fully-discounted UBL invoices were being incorrectly excluded from import. Previously, lines with zero amounts were filtered out, even when representing supplier discounts or tax adjustments. This fix ensures that all invoice lines, including those with zero amounts due to discounts, are imported for accurate reconciliation and reporting.
Original PR description
`_import_ubl_invoice_add_base_lines` filters out every imported line whose `total_included_currency` is zero, on the assumption that a zero-amount line carries no useful information. This is correct for truly empty rows, but wrong for 100%-discounted lines, an ecotax or excise row, or a returnable-packaging entry nets to zero precisely because the supplier discounted it entirely, and the line still carries data the customer needs to reconcile the bill against the original document opw-6176349 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where Jofotara was rejecting invoices due to extremely small negative discount amounts. The fix ensures that discount amounts are always non-negative by applying an absolute value function, preventing errors related to floating-point calculations and improving invoice processing with Jofotara.
Original PR description
Before this commit: 1. Create a POS order with no discount and a quantity that does not divide evenly into the unit price (e.g. price=10.0, qty=3) 2. Send the order to Jofotara Jofotara rejects the…
Before this commit:
1. Create a POS order with no discount and a quantity that does not divide evenly into the unit price (e.g. price=10.0, qty=3)
2. Send the order to Jofotara
Jofotara rejects the invoice because the AllowanceCharge/Amount on the invoice line is a small negative value like -0.000000001 with the error `"EINV_MESSAGE":"discount cannot be negative"`
This happens because _add_document_line_gross_subtotal_and_discount_vals computes the discount as: gross_subtotal - total_excluded_currency
where gross_subtotal goes through two independent rounding steps (round unit price, then round unit_price * qty). When the quantity is indivisible, the reconstituted gross_subtotal can land just below total_excluded_currency by a floating-point epsilon, producing a tiny negative discount. The same subtraction also produces a legitimate negative value for refund lines (negative quantity), which was already handled by abs() in _add_pos_order_discount_vals for the document-level total but was left unguarded at the per-line level.
After this commit:
Apply abs() to vals[f'discount_amount{currency_suffix}'] in _add_pos_order_line_allowance_charge_nodes so that discount_amount_currency is always non-negative.
opw-6183423This update optimizes the Point of Sale partner search to be faster and more responsive, especially when many partners are loaded. By limiting the displayed results and increasing the search input delay, the system now handles large searches more efficiently, providing a smoother user experience. This change focuses on performance and usability.
Original PR description
Before this commit, when high number of partners were loaded in the POS, searching for a partner was slow. The main issue was that all of the filtered partners based on the search query were being rendered, while in reality, if a query returns lots of results, the search query is not refined enough and the user is likely to type more characters to narrow down the search. So in this commit, we limit the number of rendered partners to 200, which is a reasonable number of results to display and does not cause performance issues. Moreover, the debounce time of the search input has been increased from 100ms to 500ms to further reduce the number of times the search function is called while the user is typing. opw-6215958 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug that prevented the Employees app from functioning correctly when employees have fully flexible contracts. The fix ensures that the system correctly handles contracts without a linked calendar, preventing UI errors and maintaining proper leave status calculations. This improves the usability of the HR module for all employees.
Original PR description
Steps to reproduce 1. Install hr_holidays and hr_contract. 2. Take a demo employee currently on a validated time off covering now. 3. Set the employee's running contract Working Schedule to empty…
Steps to reproduce 1. Install hr_holidays and hr_contract. 2. Take a demo employee currently on a validated time off covering now. 3. Set the employee's running contract Working Schedule to empty (fully flexible). 4. Run the "HR Contract: update state" cron (or otherwise leave the contract in state open / close, or draft + kanban Ready). 5. Open the Employees app or any view rendering that employee's chatter / follower panel. Issue A traceback "Expected singleton: resource.calendar()" is raised. If the employee's chatter is open, the failing compute is re-fired on every store refresh and the UI becomes unusable. For fully flexible contracts, hr.contract has no resource_calendar_id, so _get_calendar_periods appends period tuples with an empty calendar recordset (https://github.com/odoo/odoo/blob/c6d9fa5873eb759846e9be5b66eedb8b00c5ac11/addons/hr_contract/models/hr_employee.py#L184). _get_first_working_interval then forwarded that empty recordset to _work_intervals_batch, which calls ensure_one() and crashes. This regressed when _compute_leave_status was switched from a single calendar lookup to per-period iteration in https://github.com/odoo/odoo/commit/bf73b63eec56a822edec2d9ecfeb231a0fbfbbe8 which did not consider that a period in the chain can come from a contract with no calendar. Solution Fall back to the company's calendar when the period's calendar is empty, matching the guard already present from saas-18.4 onwards in https://github.com/odoo/odoo/commit/21f18b1a6fdbf1a01c3dda83acfa66addd01a759. opw-6168264
This update optimizes how Odoo searches for records with binary attachments. Previously, a slow search process generated a large list of attachment IDs, causing performance bottlenecks. By switching to a more efficient ‘NOT EXISTS’ query, Odoo now finds records much faster, especially in systems with many attachments.
Original PR description
Description of the issue/feature this PR addresses:
Searching for records without a binary attachment (e.g., `('binary_field', '=', False)`) previously generated a query using `NOT IN (SELECT res_id FROM ir_attachment...)`. On databases with a large `ir_attachment` table, materializing this entire list of IDs causes a significant performance bottleneck.
Replacing NOT IN with a NOT EXISTS allows PostgreSQL to short-circuit the evaluation as soon as it find a matching document, drastically reducing query execution time.
Backport of https://github.com/odoo/odoo/pull/252525
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-pr1 change
Resolved issues and error corrections
A recent update to Odoo's document signing process caused errors when downloading signed documents. This fix resolves a compatibility issue with the pypdf library, ensuring documents can be downloaded correctly. The change moves the compression step to the correct object, preventing the error.
Original PR description
This [related PR] introduced a compression pass after calls to mergePage(). However in newer versions of pypdf (>=3.5.2), compress_content_streams() can only be called on pages of PdfWriter. An error would be raised when called on pages of a PdfReader. Steps to reproduce ----- 1. Run Odoo with pypdf>=3.5.2 2. Sign and download a document in the Sign app 3. Traceback occurs Fix ---- This commit moves the compression to the writer object, after the merged page has been added. Related pr: https://github.com/odoo/odoo/pull/261879 runbot-937761