Daily updates from Odoo
Thursday, July 9, 2026
319 changes
13 changes
Enhancements to existing features
The bank reconciliation widget now sends less unnecessary data to the browser and precomputes some information on the server. This should make opening and using bank reconciliation faster on very large databases, improving accountant productivity.
Original PR description
When opening the bank rec widget on huge DB's, it takes
a lot of time to load everything.
This commit aims to improve the loading performances by
removing some JS fields:
1 - reconciled_lines_ids: We only use the first element of
this recordset in JS, so we add a new computed field
to only send 1 record to the JS
2 - hasAttachment: replace the long JS computation of
`get hasAttachment` with a python computed field.
3 - Replace matched_credit_ids and matched_debit_ids
with exchange_diff_partial_ids.
Linked:https://github.com/odoo/odoo/pull/269119
task-6275945
Forward-Port-Of: odoo/enterprise#119557Searching for customers in Point of Sale is now more responsive when many partners exist. The system now shows only a practical number of results and waits a bit longer before re-running the search while typing, which reduces delays and improves the user experience.
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 Forward-Port-Of: odoo/odoo#268658 Forward-Port-Of: odoo/odoo#264300
Resolved issues and error corrections
AI-related screens now fit better on smaller devices, making agent profiles, composer cards, and skill forms easier to read and use on mobile. This reduces wasted space and presents key information more clearly for users working from phones or tablets.
Original PR description
This commit improves the user experience of the AI modules on smaller screens by fixing several views for mobile devices. The changes include: - Adapt the AI agent form view to follow the Contacts mobile layout by centering the avatar in a circular container and improving the layout of the name and description. - Move the agent avatar next to the record name in the AI Composer kanban view to optimize space usage. - Remove unnecessary empty space in the AI Skill form view so the form uses the available width on mobile. task-6366399
Fixes an issue where using the mute button during VoIP demo calls could cause the call interface to crash. Demo calls now better simulate microphone behavior, improving reliability for demonstrations and testing.
Original PR description
Since commit [1], clicking the "mute" button during demo calls crashed. This is because the mocked SIP.js object now includes a `peerConnection` which was the guard against actually toggling microphone input. Now we do mock microphone toggling as well, preventing the crash, and making demo calls more realistic at the same time too. [1]: https://github.com/odoo/enterprise/commit/351dac8a19b581bc0892f18c3048228471c28238 Related to task-6361911
This update fixes a missing text string in the Stripe expense integration so users see the intended message instead of a deprecated or incomplete one. It is a small correction that improves clarity without changing business workflows.
Original PR description
Add missing string runbot-941402 Forward-Port-Of: odoo/enterprise#123638 Forward-Port-Of: odoo/enterprise#123495
Canadian check printing now hides check numbers on payment stubs when using pre-numbered checks. This keeps stubs consistent with the printed check and avoids duplicate or misleading check number information.
Original PR description
The check itself respected the check_manual_sequencing field, but the stubs did not. Hide the numbers on stubs as well, exactly like on US checks. task-6343701 Forward-Port-Of: odoo/enterprise#122565
This change prevents a crash that could happen when users try to split a stock transfer that has already been completed. Since there is nothing left to split in that situation, the system now exits safely instead of showing an error.
Original PR description
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an…
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an expected singleton traceback occurs. Steps to Reproduce: ========================= - Install the stock module with demo data. - Create a delivery picking for any product with a demand of 5. - Set the done quantity to 2. - Validate the picking without creating a backorder. - Try to split the validated/done picking. - An expected singleton traceback is raised. Cause of the issue: ========================= Previously, attempting to split a done picking simply returned because there was nothing left to split. After this [PR](https://github.com/odoo/odoo/pull/224952), the split action calls **message_post()** to post a note on the original picking of the generated backorder. However, no backorder is created when splitting a done picking since there is no remaining quantity to split. As a result, message_post() is called on an empty recordset, leading to an expected singleton traceback. With This Commit: ========================= Splitting a done picking has no functional purpose, as there is nothing left to split. In this case, simply return without performing any action. This preserves the previous behaviour and prevents the traceback. Forward-Port-Of: odoo/odoo#274855 Forward-Port-Of: odoo/odoo#274382
This change fixes a flaky test in the HTML editor toolbar, preventing occasional false failures during automated testing. It makes the test more reliable by checking the order of internal updates instead of relying on timing-sensitive screen changes.
Original PR description
### Description of the issue/feature this PR addresses: - Resolve non-deterministic failures in the 'toolbar should not open between double and triple click' Hoot test. - Because browser-level selectionchange events are dispatched asynchronously in the event loop, asserting on the presence of `.o-we-toolbar` in the DOM leads to timing race conditions. ### Solution: - Resolves the flakiness by introducing a wrapper method `triggerDebouncedUpdateToolbar` in `ToolbarPlugin` and refactoring the test to track method call sequences instead of asserting on DOM elements. This verifies the scheduled debounced updates in a deterministic sequence. task: https://runbot.odoo.com/odoo/error/243145 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274498 Forward-Port-Of: odoo/odoo#273303
This fix prevents the website editor from crashing when users open the Documents tab after selecting an icon in the media picker. It ensures the editor correctly distinguishes document items from icons, making the replacement flow more reliable.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
When a task is moved to another project, its followers now inherit the notification preferences set at the destination project. This ensures people continue receiving the updates they expect, such as stage changes, instead of missing important task activity.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change fixes a problem where e-invoices could be rejected by the Nilvera service when the company uses a foreign main currency. The system now always includes the required exchange rate to Turkish Lira in the invoice data, helping invoices go through successfully.
Original PR description
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency…
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency (e.g., USD) rather than the local currency (TRY). Nilvera strictly requires a valid exchange rate relative to Turkish Lira (TRY) to be included inside the XML nodes of every posted invoice utilizing a foreign currency. Functions affected: def _add_invoice_exchange_rate_nodes(self, document_node, vals): def _l10n_tr_get_currency_conversion_rate(self, invoice): Current behavior before PR: When generating an invoice where both the company's main currency and the invoice currency are foreign (e.g., USD), the system does not calculate or embed a TRY conversion/exchange rate into the invoice payload. Because this mandatory local currency reference mapping is missing, Nilvera rejects the invoice submission. Desired behavior after PR is merged: For every invoice processed via the Nilvera localization, the system will explicitly calculate and inject the exchange rate between the active invoice currency and TRY into the posted document nodes, regardless of what the underlying company's primary currency is set to. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271129 Forward-Port-Of: odoo/odoo#270531
This change prevents signed-in website visitors from being unexpectedly logged out after browsing pages when a guest chat session already exists. It improves reliability of the website experience by making sure guest tracking does not override an authenticated user’s session.
Original PR description
Before this commit, browsing any page of the website while having a guest cookie set would log out the user after a few seconds. Steps to reproduce: 1. While logged out start a live chat on "/contactus" (or get a guest cookie in any other way). 2. Log in as Marc Demo 3. Open "/contactus" (or any other website page) 4. Refresh after a few seconds -> logged out This happens since [1], which refactored the visitor page tracking. In said change, the override of `track` in `website_livechat` adds the guest to the request context (using `force_guest_env`) if the guest cookie is found. This is done to correctly connect the guest and visitor records, but will log out an authenticated user that has the guest cookie. This commit fixes the issue by only forcing the guest env if the user is not authenticated. [1] https://github.com/odoo/odoo/pull/247438 task-6369344 Forward-Port-Of: odoo/odoo#274704
This change fixes an issue where unreserving a manufacturing order could accidentally reset byproduct quantities to zero. As a result, producing the order again now correctly creates the expected byproducts, avoiding missing output and manual rework.
Original PR description
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a…
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a bom for main with component as component and byproduct as byproduct * Create and confirm a mo for main * Set qty_producing to quantity ot produce * click on "Unreserve" (do_unreserve) * click on "Check availability" (action_assign) * Produce All -> the byproducts will not be produced. Observation: ------------- When updating the qty_producing value it will also update the quantity of the byproducts moves: https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L892-L893 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L1350 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/stock/models/stock_move.py#L2382 The quantity on the byproducts move has been updated. When clicking on Unreserve it will call do_unreserve, https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L2297-L2298 It will filters the moves that do not need to be unreserved and select the others: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L900 and it will unlink all the sml from the moves: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L919 Which will set the quantity on the byproduct moves to 0. When Producing all (button_mark_done) since the qty_producing has already been set, it will simply mark the byproduct move has picked. https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L1323-L1324 In our case, this means that the no byproducts will be created since, the quantity was previously set to 0 opw-6296562 Forward-Port-Of: odoo/odoo#273739 Forward-Port-Of: odoo/odoo#272216
12 changes
Enhancements to existing features
Xendit payments now cover the Singapore market with PayNow (SGQR) support, and merchants can also accept SGD and USD. The update also adds support for additional card brands, including JCB and AMEX in supported markets, helping expand payment options for customers.
Original PR description
This commit expands Xendit support to include the Singaporean market and additional card brands. The following changes were made: - Added support for the PayNow (SGQR) payment method. - Added SGD and USD to the list of supported currencies. - Added JCB and AMEX to the supported card brands (available for some markets). - Updated the base payment provider data for Xendit to include PayNow. Task-5964309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274769 Forward-Port-Of: odoo/odoo#253542
Customers can now choose to pay at the counter even when a payment method has already been set up in self-order. This gives businesses more flexibility at checkout and avoids blocking mixed payment flows.
Original PR description
pos*: point_of_sale, pos_self_order This commit allows the user to allow his customer to pay at the counter even if they already have payment method set in the self order. task-id: 5960666 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268893 Forward-Port-Of: odoo/odoo#250364
The out-of-office banner now keeps the “Back on” status on a single line instead of wrapping onto multiple lines. This makes the header look cleaner and more aligned for a more consistent user experience.
Original PR description
Previously, the 'Back on' status in the out-of-office banner could wrap onto multiple lines, making the header appear misaligned. This PR keeps the status on a single line for a cleaner and more consistent layout. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="378" height="630" alt="image" src="https://github.com/user-attachments/assets/e4c9f278-9a65-48ad-8841-6ed059bd766d" /> </td> <td> <img width="372" height="631" alt="image" src="https://github.com/user-attachments/assets/f3dd860b-eba5-4233-a4c0-f286eec95c63" /> </td> </tr> </table> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274811 Forward-Port-Of: odoo/odoo#274050
Resolved issues and error corrections
This change prevents an error when users try to split a completed stock transfer that no longer has any remaining quantity. Instead of triggering a traceback, the system now safely does nothing, which preserves the expected behavior and avoids disruption.
Original PR description
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an…
Issue before this commit: ========================= When splitting a done picking that contains at least one stock move whose done quantity is less than the demanded quantity (product_uom_qty), an expected singleton traceback occurs. Steps to Reproduce: ========================= - Install the stock module with demo data. - Create a delivery picking for any product with a demand of 5. - Set the done quantity to 2. - Validate the picking without creating a backorder. - Try to split the validated/done picking. - An expected singleton traceback is raised. Cause of the issue: ========================= Previously, attempting to split a done picking simply returned because there was nothing left to split. After this [PR](https://github.com/odoo/odoo/pull/224952), the split action calls **message_post()** to post a note on the original picking of the generated backorder. However, no backorder is created when splitting a done picking since there is no remaining quantity to split. As a result, message_post() is called on an empty recordset, leading to an expected singleton traceback. With This Commit: ========================= Splitting a done picking has no functional purpose, as there is nothing left to split. In this case, simply return without performing any action. This preserves the previous behaviour and prevents the traceback. Forward-Port-Of: odoo/odoo#274855 Forward-Port-Of: odoo/odoo#274382
This update fixes a flaky test in the HTML editor toolbar, which was sometimes failing because browser events were processed at unpredictable times. It improves reliability in testing without changing the end-user behavior of the editor.
Original PR description
### Description of the issue/feature this PR addresses: - Resolve non-deterministic failures in the 'toolbar should not open between double and triple click' Hoot test. - Because browser-level selectionchange events are dispatched asynchronously in the event loop, asserting on the presence of `.o-we-toolbar` in the DOM leads to timing race conditions. ### Solution: - Resolves the flakiness by introducing a wrapper method `triggerDebouncedUpdateToolbar` in `ToolbarPlugin` and refactoring the test to track method call sequences instead of asserting on DOM elements. This verifies the scheduled debounced updates in a deterministic sequence. task: https://runbot.odoo.com/odoo/error/243145 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274498 Forward-Port-Of: odoo/odoo#273303
This change prevents an access error that could appear during subcontracting operations when handling serial numbers. It helps users complete the process smoothly without running into permission issues.
Original PR description
opw-6316136 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#274830 Forward-Port-Of: odoo/odoo#271739
This change prevents the website editor from crashing when a user opens the Documents tab after selecting an icon. It improves the media picker so it correctly distinguishes icons from document attachments, making the replace flow more reliable.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
This update improves the Point of Sale experience by making product cards larger so long names display correctly. It also automatically selects single-option product variants and ensures saved interface settings are restored correctly, so product details appear properly in the cart and receipt.
Original PR description
This commit fixes multiple issues: 1. Product visibility: Product card are too small, we increase their size so that big product name can be displayed properly. 2. Variant selection: When a product has attributes with only one choice the choice is not selected automatically. We select it in this commit such that the information is displayed properly in the cart and receipt. 3. uiState not updated: When we restore the uiState of a record, we do not take into account that the uiState architecture might have changed. We now init the uiState before restoring it so new fields are properly initialized even when not present in the saved uiState. task-id: 6344288 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272843
When a task is moved to another project, followers now inherit the notification settings of the new project. This ensures people continue receiving the right updates, such as stage changes, instead of missing important task activity.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change ensures e-invoices sent through the Turkish Nilvera integration always include the exchange rate to TRY, even when the company’s main currency is not TRY. It prevents invoice rejections by making the XML meet Nilvera’s required currency rules.
Original PR description
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency…
Description of the issue/feature this PR addresses: This PR resolves an integration failure with the Nilvera e-invoicing provider when a company’s primary currency is configured to a foreign currency (e.g., USD) rather than the local currency (TRY). Nilvera strictly requires a valid exchange rate relative to Turkish Lira (TRY) to be included inside the XML nodes of every posted invoice utilizing a foreign currency. Functions affected: def _add_invoice_exchange_rate_nodes(self, document_node, vals): def _l10n_tr_get_currency_conversion_rate(self, invoice): Current behavior before PR: When generating an invoice where both the company's main currency and the invoice currency are foreign (e.g., USD), the system does not calculate or embed a TRY conversion/exchange rate into the invoice payload. Because this mandatory local currency reference mapping is missing, Nilvera rejects the invoice submission. Desired behavior after PR is merged: For every invoice processed via the Nilvera localization, the system will explicitly calculate and inject the exchange rate between the active invoice currency and TRY into the posted document nodes, regardless of what the underlying company's primary currency is set to. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271129 Forward-Port-Of: odoo/odoo#270531
This change prevents paid point-of-sale orders from creating duplicate payment lines when they are synced again. It also avoids a crash that could happen if the system tried to process a payment that had already been removed, making payment updates more reliable.
Original PR description
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was…
A paid order can reach `sync_from_ui` more than once. In that case the order falls into the else branch of `sync_from_ui` and its payments are re-processed through `process_saved_payments`, which was not idempotent and led to two issues: - The change/return cash payment is generated server-side in `_process_payment_lines` and has no uuid, so `_update_lines` cannot deduplicate it. Each extra sync therefore created an additional return payment. It is now removed before being recomputed, which also keeps it correct when the payments are edited after payment (new return amount, or no change at all). - `_update_lines` replays the client commands as-is. On a second sync, a delete command (`[2, id]`) targets a payment that the first sync already removed, and `_create_pm_change_log` crashed with a MissingError while reading the deleted record. Update/delete/unlink commands referencing records that no longer exist are now skipped. Note that delete/unlink commands only carry 2 elements, so the check runs before the `len(line) < 3` guard. Steps to reproduce: - Pay an order, then re-sync it (or edit its payments and sync again). => the return payment was duplicated, or a MissingError was raised. opw-6327912 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272539
This update prevents manufacturing byproducts from being reset to zero when a manufacturing order is unreserved and then re-checked. As a result, businesses can safely unreserve and replan production without losing expected byproduct output.
Original PR description
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a…
On a mo that has byproducts, if you unreserve, it will also set the quantity of byproducts to 0 Steps to reproduce: ------------------- * Create a Products main, component and byproduct * Create a bom for main with component as component and byproduct as byproduct * Create and confirm a mo for main * Set qty_producing to quantity ot produce * click on "Unreserve" (do_unreserve) * click on "Check availability" (action_assign) * Produce All -> the byproducts will not be produced. Observation: ------------- When updating the qty_producing value it will also update the quantity of the byproducts moves: https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L892-L893 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mrp/models/mrp_production.py#L1350 https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/stock/models/stock_move.py#L2382 The quantity on the byproducts move has been updated. When clicking on Unreserve it will call do_unreserve, https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L2297-L2298 It will filters the moves that do not need to be unreserved and select the others: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L900 and it will unlink all the sml from the moves: https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/stock/models/stock_move.py#L919 Which will set the quantity on the byproduct moves to 0. When Producing all (button_mark_done) since the qty_producing has already been set, it will simply mark the byproduct move has picked. https://github.com/odoo/odoo/blob/aca2e226143487b421f79194d677bb48d5da1358/addons/mrp/models/mrp_production.py#L1323-L1324 In our case, this means that the no byproducts will be created since, the quantity was previously set to 0 opw-6296562 Forward-Port-Of: odoo/odoo#273739 Forward-Port-Of: odoo/odoo#272216
8 changes
Enhancements to existing features
The out-of-office banner now keeps the “Back on” status on a single line instead of allowing it to wrap. This makes the header look cleaner and more aligned, improving the overall appearance of the banner.
Original PR description
Previously, the 'Back on' status in the out-of-office banner could wrap onto multiple lines, making the header appear misaligned. This PR keeps the status on a single line for a cleaner and more consistent layout. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="378" height="630" alt="image" src="https://github.com/user-attachments/assets/e4c9f278-9a65-48ad-8841-6ed059bd766d" /> </td> <td> <img width="372" height="631" alt="image" src="https://github.com/user-attachments/assets/f3dd860b-eba5-4233-a4c0-f286eec95c63" /> </td> </tr> </table> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274811 Forward-Port-Of: odoo/odoo#274050
Resolved issues and error corrections
This update prevents Redsys from rejecting some international payments when a customer has no state set or no valid state code. Odoo now only sends the state information when it is available, which lets those payments go through successfully.
Original PR description
### Description of the issue/feature this PR addresses: International production payments processed via Redsys are failing with error code 9754 (SIS0754). This rejection occurs because the EMV3DS (3D…
### Description of the issue/feature this PR addresses: International production payments processed via Redsys are failing with error code 9754 (SIS0754). This rejection occurs because the EMV3DS (3D Secure 2.0) payload is sending the billAddrState field with an invalid ISO code format for non-Spanish customers or customers without a state configured. ### Current behavior before PR: The _redsys_prepare_merchant_parameters method hardcodes the billAddrState key into the DS_MERCHANT_EMV3DS dictionary payload. If self.partner_state_id.code is missing or empty, Odoo sends an empty/falsy value. Because Redsys enforces strict EMV3DS format validation, it rejects the entire transaction for having an invalid state format rather than simply ignoring the empty value. ### Desired behavior after PR is merged: The DS_MERCHANT_EMV3DS dictionary is now constructed dynamically. The billAddrState key is only appended to the payload if a valid state code actually exists for the partner. RedSys allows this field to be optional, so omitting the key entirely when unavailable causes Redsys to skip the validation for that specific field, allowing certain international payments to process successfully. opw-6237764 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273214 Forward-Port-Of: odoo/odoo#270899
When a receipt triggers an expiration warning before a lot record has been created, the message now falls back to the lot number entered by the user. This prevents confusing “False, False” messages and makes the warning clear and usable during receipt validation.
Original PR description
From saas-18.4, the expiration confirmation wizard can be triggered not only from expired lots, but also from stock move lines whose `removal_date` has passed. For incoming receipts, tracked products…
From saas-18.4, the expiration confirmation wizard can be triggered not only from expired lots, but also from stock move lines whose `removal_date` has passed. For incoming receipts, tracked products use the `lot_name` field when the user is entering the lot. The corresponding `lot_id` is only created later once the receipt is validated. As a result, it is possible for the expiration confirmation wizard to be displayed before the lot exists. In this situation, it attempts to display the product and lot information using `lot_id`, which is still empty, causing the message to show "False, False" instead of the actual lot name entered by the user. It should use the move line information as a fallback when no `lot_id` has been created yet so it still displays the correct product and lot name. Steps to reproduce 1. Enable Product Expiry. 2. Create a storable product with: - Tracking: By Lots - Use Expiration Date: enabled - Removal Time > 0 3. Create a receipt for the product. 4. Open Detailed Operations. 5. Enter a new lot number in the Lot/Serial Number field. 6. Ensure the removal date is in the past and validate the receipt. Related Tickets: opw-6303140 Forward-Port-Of: odoo/odoo#273970 Forward-Port-Of: odoo/odoo#273143
When a message is scheduled to be sent later from an email template, all of its attachments are now correctly linked to the scheduled record. This prevents access issues for other users when they open the related document later.
Original PR description
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message…
**Problem:** When scheduling a message using an email template with custom attachments, those attachments will not have their `res_model` and `res_id` updated to relate to the scheduled message record. This can lead to access errors. **Cause:** When composing a message using an email template with attachments, those attachments are created with their `res_model` and `res_id` values corresponding to the mail composer record. However, when scheduling a message, only attachments with no `res_id` value (or a value of 0) are updated to correspond to the scheduled message record. https://github.com/odoo/odoo/blob/77b180e8251fb8019e0034e1c2f485fd2c34ea4e/addons/mail/wizard/mail_compose_message.py#L1198-L1201 https://github.com/odoo/odoo/blob/30ca89b9e0d3c43d019167ec2de816c263f4bb92/addons/mail/models/mail_scheduled_message.py#L86 **Purpose:** Modify the `mail.scheduled.message` override of `create` to not require an attachment have no `res_id` value to be properly updated. **Steps to Reproduce in Runbot:** 1. Add an attachment to an email template. 2. Open a mail composer using that email template, then schedule the message for later. 3. Attempt to view the scheduled message with a different user. More specific example flow: 1. Add an attachment to the Sales: Send Quotation email template. 2. Create a Quotation and send it with the Send by Email button, selecting Send Later instead of Send. 3. Attempt to view the Quotation with a different user. opw-6293587 Forward-Port-Of: odoo/odoo#272261
This change fixes a test that sometimes failed unpredictably when checking toolbar behavior during quick clicks. It makes the test more reliable by verifying the sequence of actions instead of depending on a browser timing detail, reducing false failures in development and continuous testing.
Original PR description
### Description of the issue/feature this PR addresses: - Resolve non-deterministic failures in the 'toolbar should not open between double and triple click' Hoot test. - Because browser-level selectionchange events are dispatched asynchronously in the event loop, asserting on the presence of `.o-we-toolbar` in the DOM leads to timing race conditions. ### Solution: - Resolves the flakiness by introducing a wrapper method `triggerDebouncedUpdateToolbar` in `ToolbarPlugin` and refactoring the test to track method call sequences instead of asserting on DOM elements. This verifies the scheduled debounced updates in a deterministic sequence. task: https://runbot.odoo.com/odoo/error/243145 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274498 Forward-Port-Of: odoo/odoo#273303
When a message is edited, its type now stays the same instead of being changed to a comment. This keeps message records consistent and avoids unexpected behavior when users update content.
Original PR description
Set message_type as 'comment' only when creating a new message. Updating content should not change it. Task-6368820 Part of Task-3704380 Forward-Port-Of: odoo/odoo#274988
This change prevents the website editor from crashing when a user opens the Documents tab after selecting an icon. It improves stability in the media replacement dialog, so users can switch media types without losing their work or encountering an error.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
This change ensures that databases prepared for testing or staging keep using Peppol demo mode even if the Peppol feature is installed later. It avoids accidentally sending documents to the live Peppol network from a neutralized database.
Original PR description
When Peppol is installed on a database that was already neutralized (ex: a staging database where the feature is enabled after the neutralization happened), the account_peppol.edi.mode parameter is not set: data/neutralize.sql only runs at neutralization time, not when the module is installed afterwards. The demo/ data that also sets this parameter is not loaded on databases without demo data (real production/staging databases). As a result, _get_peppol_edi_mode() falls back to 'prod' and the neutralized database registers and sends documents against the live Peppol network. Steps to reproduce: - Neutralize a database on which Peppol is not installed yet - Install the account_peppol module - Open the Peppol settings / registration wizard: the mode is Production instead of Demo Force the demo mode in the pre_init_hook when the database is neutralized, mirroring data/neutralize.sql opw-6307710 Forward-Port-Of: odoo/odoo#274700 Forward-Port-Of: odoo/odoo#273019
7 changes
Enhancements to existing features
The out-of-office banner now keeps the “Back on” status on a single line instead of wrapping. This improves the visual alignment of the header and makes the banner look cleaner and more consistent for users.
Original PR description
Previously, the 'Back on' status in the out-of-office banner could wrap onto multiple lines, making the header appear misaligned. This PR keeps the status on a single line for a cleaner and more consistent layout. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="378" height="630" alt="image" src="https://github.com/user-attachments/assets/e4c9f278-9a65-48ad-8841-6ed059bd766d" /> </td> <td> <img width="372" height="631" alt="image" src="https://github.com/user-attachments/assets/f3dd860b-eba5-4233-a4c0-f286eec95c63" /> </td> </tr> </table> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274811 Forward-Port-Of: odoo/odoo#274050
Resolved issues and error corrections
This change fixes a flaky automated test in the email/content editor toolbar. It makes the test reliable by checking the order of internal updates instead of depending on browser timing, which helps prevent random failures in development and continuous integration.
Original PR description
### Description of the issue/feature this PR addresses: - Resolve non-deterministic failures in the 'toolbar should not open between double and triple click' Hoot test. - Because browser-level selectionchange events are dispatched asynchronously in the event loop, asserting on the presence of `.o-we-toolbar` in the DOM leads to timing race conditions. ### Solution: - Resolves the flakiness by introducing a wrapper method `triggerDebouncedUpdateToolbar` in `ToolbarPlugin` and refactoring the test to track method call sequences instead of asserting on DOM elements. This verifies the scheduled debounced updates in a deterministic sequence. task: https://runbot.odoo.com/odoo/error/243145 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274498 Forward-Port-Of: odoo/odoo#273303
This change stops Odoo from reprocessing work entries when no eligible employees remain after exclusions. It prevents a fallback that could unexpectedly scan many employees and slow down large databases, while keeping existing validated work entries intact.
Original PR description
**Steps to Reproduce:** - Create an employee with at least one validated work entry. - Modify the employee's resource_calendar_id. - The schedule change triggers work entry recomputation. - During…
**Steps to Reproduce:** - Create an employee with at least one validated work entry. - Modify the employee's resource_calendar_id. - The schedule change triggers work entry recomputation. - During regeneration, the employee is excluded because of the validated work entry. - No valid employees remain for regeneration. **Issue:** - Employees with validated work entries are excluded from: `valid_employees = self.employee_ids - self.validated_work_entry_employee_ids` - When all employees are excluded, `valid_employees` becomes empty. - The flow still calls: `valid_employees.generate_work_entries(date_from, date_to, True)` - An empty employee recordset causes `generate_work_entries()` to follow the global generation path and fetch all employee versions in the requested period. `_get_all_versions_with_contract_overlap_with_period(date_start, date_stop)` - This can trigger unintended global work entry regeneration and cause severe performance issues on large databases. **Root Cause:** - The regeneration flow does not stop when no valid employees remain after excluding employees having validated work entries. - As a result, generate_work_entries() is called with an empty employee recordset, which falls back to the global generation path. **Solution:** - Stop the regeneration flow when the valid employee recordset is empty Because the employee already has a valid work entry, there is no need to regenerate. **Result:** - Prevents unintended generation on all employee versions. - Avoids unnecessary performance degradation on large databases. **OPW-6290122** 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#270728
This fix prevents an existing message from being reclassified when its content is updated. It helps keep message records consistent and avoids unexpected changes in how messages are handled or displayed.
Original PR description
Set message_type as 'comment' only when creating a new message. Updating content should not change it. Task-6368820 Part of Task-3704380 Forward-Port-Of: odoo/odoo#274988
This update fixes a crash that could happen in the website editor when a user selected an icon and then opened the Documents tab while replacing media. It improves the editor’s stability so users can switch between media options without losing work or hitting an error.
Original PR description
### Steps to reproduce: - Open the website editor and insert a snippet. - Inside the snippet, add an image and a document via /media. - Select the image, click Replace, pick an icon. - Click the icon, then click Replace from the sidebar. - In the dialog, click the Documents tab. - Traceback occurs. ### Root cause: - Both icon and document box elements are `<span>` tags. `DocumentSelector` inherits `selectInitialMedia()` from `FileSelector` which only checks the tag name, so it incorrectly returns true for icons. This causes `fetchAttachments` to call `querySelector(a)` on the icon span, which returns null and crashes. ### Solution: - Override `selectInitialMedia()` in `DocumentSelector` to also check for the `o_file_box` class. Add optional chaining on `querySelector(a)` as a safety net. task-6310147 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270548
When a task is moved from one project to another, its followers now inherit the notification preferences of the destination project. This prevents people from missing important updates, such as stage changes, after a task is reassigned.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change fixes an issue in list views where selecting rows also blocked copying or selecting the totals shown in the footer. Users can now highlight footer totals even when one or more rows are selected, making it easier to reuse or compare values.
Original PR description
Before this commit, selecting one or more rows in a list view disabled text selection on the whole list, which also prevented users from selecting the totals displayed in the footer. This commit fixes the issue on the list footer, so totals remain selectable even when rows are selected. task:6240238 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272126
1 change
Resolved issues and error corrections
This change ensures that databases which were neutralized before Peppol was installed still stay in demo mode. It prevents test or staging environments from accidentally connecting to the live Peppol network and sending real documents.
Original PR description
When Peppol is installed on a database that was already neutralized (ex: a staging database where the feature is enabled after the neutralization happened), the account_peppol.edi.mode parameter is not set: data/neutralize.sql only runs at neutralization time, not when the module is installed afterwards. The demo/ data that also sets this parameter is not loaded on databases without demo data (real production/staging databases). As a result, _get_peppol_edi_mode() falls back to 'prod' and the neutralized database registers and sends documents against the live Peppol network. Steps to reproduce: - Neutralize a database on which Peppol is not installed yet - Install the account_peppol module - Open the Peppol settings / registration wizard: the mode is Production instead of Demo Force the demo mode in the pre_init_hook when the database is neutralized, mirroring data/neutralize.sql opw-6307710 Forward-Port-Of: odoo/odoo#273458 Forward-Port-Of: odoo/odoo#273019
46 changes
New functionality added to Odoo
Adds the Vietnam-required General Ledger report format S03b-DN so companies can produce reports aligned with Vietnamese Accounting Standards. The report calculates and displays counterpart accounts, debit and credit balances, period totals, and flags entries that need better labeling for accurate reporting.
Original PR description
Vietnamese Accounting Standards (VAS) require a specific format for the General Ledger (S03b-DN), which strictly mandates the display of counterpart accounts for every transaction line, along with…
Vietnamese Accounting Standards (VAS) require a specific format for the General Ledger (S03b-DN), which strictly mandates the display of counterpart accounts for every transaction line, along with specific debit/credit balances and period totals. Because Odoo's default general ledger does not natively compute and display counterparts in the exact layout required by VAS, a custom report engine and handler were introduced. Technical decisions: * Implemented a custom SQL query to calculate counterpart accounts dynamically. Instead of forcing rigid data entry constraints on the user, it uses a matching heuristic based on balanced amounts and identical labels to pair counterpart lines (handling 1-to-1, 1-to-N, and proportional splits). * Tax journal lines are isolated, grouped by account, and split proportionally to ensure accurate counterpart reflection. * Added a post-processor and custom UI warnings to handle edge cases where lines cannot be matched cleanly (e.g., complex N-to-N entries without matching labels). These are isolated into an "Uncategorized" section to prompt the user to correct their entry labels. task-6092253
Enhancements to existing features
Expenses created from company card usage now generate an activity categorized as a document. This makes the follow-up clearer for employees and managers handling expense receipts and supporting paperwork.
Original PR description
Improvement of some UX about expense: - When an expense is created via a card use, the type of the created activity is now 'Document' task-6237021
The VoIP call screen now shows "Calling..." while an outgoing call is still connecting instead of displaying a timer at 00:00. This gives users a clearer indication of the call state and avoids confusion before the call is answered.
Original PR description
task-6361911
The timesheet leaderboard header has been redesigned to show the billable time target and the current month period. This gives users clearer context for their performance metrics and helps them compare progress against monthly expectations.
Original PR description
In this commit, we redesign the timesheet-leaderboard KPI header. Specifically, we add the billable time target and the current month period. task-6103977
Businesses can now assign specific deferred revenue or expense accounts to individual income and expense accounts, while still keeping company-wide defaults as a fallback. Deferred revenue and expense reports also show upcoming recognition split between amounts due within 12 months and after 12 months, improving financial visibility.
Original PR description
*accountant, reports Purpose: Supporting multiple deferred accounts allow businesses to use different deferred revenue/expense accounts based on the related income or expense account, while maintaining the existing company-wide deferred account settings as default. Changes: A "Deferred Account" field is added to the income or expense type accounts form to allow the user to override the defaults. On deferred revenues/expenses reports, the column "Later", representing amount to be recognized, is split into two columns, "Within 12 months" to represent amounts to be recognized within the year and "After 12 months" to represent amounts to be recognized after a year. task-6293902
Invoice extraction now uses the account name and tax to label grouped tax lines instead of relying on partner names and dates read by OCR. This reduces confusing or incorrect labels caused by OCR misreads and makes invoice review more reliable.
Original PR description
Previously, when a user enabled 'Single Invoice Line Per Tax', the tax group contained the partner name and date. However, the OCR would sometimes misclassify the partner name, resulting in random text appearing in the label. To fix this, we decided to use the account name and tax as the label instead. task-6159843
UK VAT return filing now warns users when their company belongs to a tax unit and guides them to file through that tax unit. When a tax unit return is filed, the HMRC connection and submission use the tax unit VAT number, reducing filing errors and compliance risk.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#123166 Forward-Port-Of: odoo/enterprise#107253
Hong Kong payroll can now use the scheduled payroll data update process. This helps keep standard, non-customized salary rules current automatically, reducing manual maintenance for users.
Original PR description
Currently, the "Payroll: Update data" cron doesn't work for HK payroll as we never set up the _get_data_files_to_update. We can set up the list of data files to keep up to date to better support our users by automatically keeping non-edited salary rules up to date. task-6360339 Forward-Port-Of: odoo/enterprise#123204 Forward-Port-Of: odoo/enterprise#122777
The self-ordering point of sale module now relies on the existing point of sale box module for printer box details instead of defining them again. This reduces duplication and helps keep configuration behavior consistent across related point of sale features.
Original PR description
Remove `proxy_obox_id` from `pos.printer` model, in `obox_pos_self_order` and change `obox_pos_self_order` dependency to `obox_point_of_sale` instead of `obox`. The field `proxy_obox_id` is defined in `obox_point_of_sale` module.
Point of Sale appointment dialogs now have better sizing and spacing, making them easier to read and use. Dialogs also get a consistent backdrop so users can close them more easily, improving the overall experience.
Original PR description
This PR adapts the size and spacing of POS dialogs to improve the design and usability of the interface. It also adds backdrop to POS dialogs to allow the user to easily close a dialog when needed. This allows for greater consistency, as previously only a few dialogs had this backdrop. task-5187182 commu-PR: https://github.com/odoo/odoo/pull/258131
Project document folder access is now updated when people are added to or removed from a project. This helps ensure collaborators get editing access when invited and lose access when no longer following restricted projects.
Original PR description
Before this change: - Subscribing or unsubscribing a partner from a project did not impact access rights on the related documents folder; users always retained access to the folder. After this change: - Subscribing a partner grants `edit` access to the project folder. - Unsubscribing removes access when `privacy_visibility` is `invited_users` or `followers` task-5993203
Sales teams can now manually choose which website is linked to an order when it was not created through eCommerce. This helps customer email links and preview actions open the correct website, also covering related subscription and rental flows.
Original PR description
The goal of this change is to allow manually selecting the website linked to an order (if the order does not come from eCommerce). This ensures that email links and the Preview button open the correct website. This change also applies to the Rental module. PR: https://github.com/odoo/odoo/pull/255763 Upgrade: https://github.com/odoo/upgrade/pull/9804 task-6059112
This update changes many accounting-related automated tests to run in a more realistic test environment instead of relying on elevated administrator access. This helps ensure future changes are validated under conditions closer to everyday use, reducing the risk of hidden permission-related issues.
Resolved issues and error corrections
IoT device logs sent to the server are now recorded at a lower severity level. This reduces unnecessary alert noise and helps prevent monitoring tools like Sentry from being overwhelmed, without changing user-facing IoT behavior.
Original PR description
Each time IoT box sends its logs to the server (route `/iot/log`), we then print them with the same log level. However, IoT box logs can be quite noisy (for instance when there are some connection issues), which affects the logs. Sentry side, it also implies a huge wave of useless events that reach the limits of our subscription. The logs management have been improved on next versions. In the meantime, we should at least decrease the logger level so we can keep working on Sentry Forward-Port-Of: odoo/enterprise#122426
The Avalara tax configuration screen now points users to the current documentation page. This prevents users from landing on an outdated help article when looking for setup guidance.
Original PR description
Documentation URL changed from `finance/accounting/taxes/avatax/avalara_included` to `finance/accounting/taxes/avalara`. task-6371352
Cancelled UrbanPiper delivery orders are now excluded from active delivery counts. This prevents affected POS sessions from failing to reopen after a delivery provider cancels an order.
Original PR description
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the…
### Steps to reproduce 1. Configure UrbanPiper and start a POS session. 2. Receive an order from the delivery provider. 3. Accept the order and mark it as **Ready**. 4. Cancel the order from the delivery provider. 5. Reopen the running POS session. ### Current behavior When a delivery provider cancels an order, the `delivery_status` is updated to `cancelled`, while the POS order state remains (`draft`, `paid`, or `done`). As a result: * Cancelled deliveries are still included in the active delivery order count. * `_get_urbanpiper_order_count()` attempts to map the `cancelled` status, which is not present in `status_map`, raising a `KeyError`. * The POS UI fails to load, preventing users from reopening the running session. ### Expected behavior Cancelled delivery orders should not be considered active delivery orders and should not be included in the delivery status count, allowing the POS session to open normally. ### Solution Exclude orders with `delivery_status = 'cancelled'` from the active delivery order count computation. This prevents the `KeyError` and ensures cancelled delivery orders are ignored when computing active delivery statistics. [Video reproducing the issue](https://drive.google.com/file/d/1XdiylekWV-q6LTbvhCgbyd_KDKlG2imz/view?usp=sharing) --- **opw-6353861** Forward-Port-Of: odoo/enterprise#122798
This fix prevents users without Payroll permissions from seeing an error when opening Working Schedules in the Employees app. It adds an access check so Belgian payroll-specific reorganisation data is only read when the user has the right permissions.
Original PR description
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees…
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees → Configuration → Working Schedules. **Actual Result:** A traceback is triggered after opening the record. ```python Failed to read field resource.calendar.l10n_be_reorganisation_measure_ids You are not allowed to access 'BE: Reorganisation Measure.' (l10n.be.reorganisation.measure) records. This operation is allowed for the following groups: - Payroll/Assistant Contact your administrator to request access if necessary. ``` **Issue:-** The traceback is caused by the following commit introduced in v19.2 [here](https://github.com/odoo/enterprise/commit/e1092393ff99e9dad84ea8b9d6066e0bc61d6312) In this commit, a new computed field `l10n_be_reorganisation_measure_ids` was added on `resource.calendar`. The field is computed and store=true when the read function is called, and reads the data from the database at that time; The payroll doesn't have any access rights due to the error **Solution:** To fix this issue, a group access check is added inside the field Ticket:- 6245936 Forward-Port-Of: odoo/enterprise#119518
The Journal Audit report PDF now avoids adding an empty final page when the global tax summary is not included. This improves report presentation and prevents users from receiving or sharing documents with unnecessary blank pages.
Original PR description
Steps to reproduce: 1. Set the active company as My Company (san francisco) 2. Navigate to Accounting > Review > Journal Audit 3. Remove all journals from the report except Bank and Misc. 4. Use the PDF action button to print the report. 5. The last page of the report is completely empty. https://drive.google.com/file/d/1otpniJgt1UNCe2hrUBwqIK58dGuXpu8T/view?usp=sharing This commit ensures that the Journal Audit report does not have blank pages when the global tax summary section is not present. It uses some features of QWeb outlined in the following docs article: https://www.odoo.com/documentation/19.0/developer/reference/frontend/qweb.html#loops opw-6224670 Forward-Port-Of: odoo/enterprise#122704 Forward-Port-Of: odoo/enterprise#121068
Twitter/X posts now save the reply count provided by the platform's API. This lets users see comment activity alongside other engagement metrics, giving a more complete view of post performance.
Original PR description
Twitter/X tweet metrics returned by the API include the number of replies in the `public_metrics.reply_count` field. This commit stores that value on social stream posts so the comments count can be displayed alongside other engagement metrics. API Documentation: https://docs.x.com/x-api/fundamentals/metrics#post-metrics Task-6251172 Forward-Port-Of: odoo/enterprise#120182
Fixes issues in subscription loyalty flows so recurring invoices grant the right reward points and respect the selected point calculation mode. It also prevents incorrect negative reward invoice lines when points run out and restores missing recurring options in loyalty rules and rewards.
Original PR description
This commit fixes the following problems in the new module: - New invoices sometimes could not grant points according to the specified rules. - The reward point mode was not being taken into account and was giving a flat amount of points. - Reward lines were being invoiced with a negative amount when there was no more points in the loyalty card. - The 'Recurring' option in conditional rules and reward were not showing sometimes for an unknown reason. task-6153127 Forward-Port-Of: odoo/enterprise#116713
Timesheet Assistant suggestions are now cleaner and more accurate, with leave time excluded from suggested totals and to-do tasks hidden until they are linked to a project. Users also get keyboard shortcuts and default names for unnamed suggestions, making timesheet entry faster and less confusing.
Original PR description
## Expected Behavior After Commit - Remove the green highlight when selecting a suggestion. - Add shortcuts for timesheet creation buttons. - Allow calendar events to be considered side activities - Exclude leave time from total hours, as leave time is already counted in the timesheet. - Do not show to‑do tasks (tasks without a project) in suggestions. - Restore previous suggestions for to‑do tasks when they later become linked to a project. - Add a default name for suggestions that do not have one. - Add hotkeys to Timesheet Assistant task-[6191451](https://www.odoo.com/odoo/project/4105/tasks/6191451) Forward-Port-Of: odoo/enterprise#121085 Forward-Port-Of: odoo/enterprise#120057
The scheduled check for Mexican electronic invoice status now correctly continues when more documents remain than the configured batch size. This prevents invoices from being left unprocessed after the first batch, improving reliability for companies using Mexican e-invoicing.
Original PR description
Steps to reproduce ----------------- - Install l10n_mx_edi; - Switch to the mexican company; - Create 3 invoices for the mexican company (you will need to set an UNSPSC code on the products); - Send them to CFDI; - Go to the scheduled action "Automatic update of state on the SAT" and add "batch_size=2" to the method's parameters; - Manually run the cron; - Only two invoices will be updated, the cron is not retriggered to process the remianing one. Why is it hapening ------------------ We set a limit of batch_size + 1 in the search method, and the cron is retriggered if and only if the number of documents fetched is equal to the batch size, meaning there is no more documents to fetch. This should be triggered if we fetched more documents than the batch size. opw-6328118 Forward-Port-Of: odoo/enterprise#122659
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior 12 months. This improves accuracy for employees who have worked less than a year or have other partial-period situations, reducing payroll errors.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903 Forward-Port-Of: odoo/enterprise#122580
This fixes an issue in Planning tests where the schedule could open on the wrong week when run on Sundays. The change makes the split shift flow more reliable by avoiding a layout problem caused by the side panel, reducing false failures and improving confidence in planning updates.
Original PR description
Forward-Port-Of: odoo/enterprise#123069
Task progress shading in the Gantt view now shows the correct proportion of completed work. This makes planning views easier to read and prevents users from misinterpreting partially completed tasks as barely started.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#122899 Forward-Port-Of: odoo/enterprise#111270
Users creating purchase approval requests will no longer be blocked when a product has vendor pricing records linked to vendors they are not allowed to access. This keeps RFQ approval creation working correctly in multi-company setups while respecting access permissions.
Original PR description
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two…
**Issue** Having supplier pricelists with at least one vendor inaccessible to the current user can trigger an access error when creating an RFQ approval request. **Steps to reproduce** - Have two companies A and B and two users u1 and u2 - user u2 only have access to company A - With user u1: - Create two vendors v1 and v2 without any company assigned - Create vendor pricelists for a product for each vendor and assign the company A to the pricelist - Add the company B for the vendor v2 - With user u2: - Open approval application - Try to create an approval for an RFQ for that product (the vendor v1 will be automatically selected) - Save it -> An access error is thrown **Cause** Saving the approval request computes `has_no_seller`, which calls `_select_seller`: https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/views/approval_product_line_views.xml#L9 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L32 https://github.com/odoo/enterprise/blob/03c737685ff6dfc95a8bc72491646774fc426b1f/approvals_purchase/models/approval_product_line.py#L62-L70 Which filtered the right seller https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L759 By preparing the sellers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L721 https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_product.py#L712 Please note that `self.seller_ids` contains both sellers (even v2) By filtering the suppliers: https://github.com/odoo/odoo/blob/c37e76850d3ff790b76493bd1003d80e170bd4bf/addons/product/models/product_supplierinfo.py#L104-L105 But at that point, one of the supplier in `self`, can be accessed, thus an access error is thrown while trying to access its associated `partner_id`. opw-6203910 Forward-Port-Of: odoo/enterprise#121008 Forward-Port-Of: odoo/enterprise#120251
Bank statement imports now show a specific error when a file contains only zero-amount transactions. This helps users understand the real issue instead of seeing a misleading duplicate-import message.
Original PR description
When importing bank statements, files containing only zero-amount transactions trigger the same generic "duplicate" UserError as files that have already been imported. We now explicitly check for zero-amount lines separately to raise a distinct UserError. opw-6237659
Fixes an issue that prevented the Planning Analysis report from opening when Field Service Planning was installed. The Priority filter is now placed correctly, avoiding a crash and restoring access to the report.
Original PR description
Steps to reproduce: - 1. Install `planning_field_service`. 2. Open Planning > Reporting > Planning Analysis. Issue: - The view crashes with `UncaughtPromiseError > Error: Attribute "domain"` is missing, and the Planning Analysis report cannot be opened. Cause: - The xpath adding the "Priority" filter anchors on `//filter[@name='unpublished_shifts']`, which is a child of the "Status" filter. As a result, "Priority" is inserted inside "Status", and it requires a `domain` on any filter nested inside another filter. "Priority" has none. Fix: - Anchor the xpath on `//filter[@name='status']` instead. task-6358804 Forward-Port-Of: odoo/enterprise#122751
Fixed an error that could stop Belgian CODA bank statement files from importing when they contained type 4 blocks. This helps Belgian accounting users complete bank imports reliably without manual workarounds or support intervention.
Original PR description
### Issue: After the fix in commit (https://github.com/odoo/enterprise/commit/3ef8ae7a6b8eb362e18c74dfab9aadce792b5dc2), importing a CODA file containing a type 4 block raises a traceback ### Cause: That commit introduced `communication_struct_by_ref_move`, which iterates over all lines and accesses `line['communication_struct']` Type 4 lines are not assigned a `communication_struct` value by the parser in `_get_coda_file_statements` Accessing the key directly raises a `KeyError` in `_get_coda_final_statements` in `communication_struct_by_ref_move` ### Steps to reproduce: - Install `l10n_be_coda` - Switch to the BE company - Create a Bank Journal with account `BE33737018595246` - Go to the Accounting Dashboard and import a CODA file containing a type 4 block (Like the one on the ticket) Before the fix, a traceback is raised on import opw-6363148 Forward-Port-Of: odoo/enterprise#123222
This fix ensures the snippet selection dialog appears in front of the email editing window when the AI chatbox is active. Users can now add snippets normally without the editor becoming blocked or save and discard actions freezing.
Original PR description
When an AI chatbox is active, all non-error dialog modals are set to be behind the chatbox through their z-index. This causes an issue where the dialog modal to add new snippets to a mailing is set behind the fullscreen edit window, preventing its use and freezing the use of some commands (save & discard). This commit restores the snippet dialog's z-index to its original value. task-6321624
Users can now dismiss the installer and web watcher warning banners in the Timesheets Assistant without seeing an error. This keeps the assistant interface clean and avoids confusion from banners that previously stayed visible after closing them.
Original PR description
Issue: - Closing the installer banner or the web watcher warning banner in the Timesheets Assistant raises an Owl error and leaves the banner visible. Cause: - Both buttons bind their handler with a bare method name, e.g. `t-on-click="onDismissConnectionWarning"`. Bare identifiers are resolved against the template rendering context, which no longer exposes component methods. Fix: - Reference the handlers through `this`. task-6373382 Forward-Port-Of: odoo/enterprise#123527
This update corrects how accounting reports are extended and moves Luxembourg-specific export logic into the appropriate wizard. The change reduces maintenance risk and helps keep localization behavior isolated without changing day-to-day business workflows.
Original PR description
[FIX] account_reports: fix inheritance account.report is a Model, not an AbstractModel. Inheriting it as an AbstractModel had not effect so far, but this is the proper way. ---------------------------------- [FIX] l10n_lu_reports: no l10n-specific code on account.report Unless absolutely necessary, localizations should never inherit account.report and define all the custom code they need in custom handlers. In this case, this code was only used for an export through a wizard, so we moved it to that wizard.
This fixes an error that could prevent users from opening the task Gantt view when grouping tasks by Sale Order Item. The progress calculation now uses the current task hours field, so project and sales teams can view grouped planning information without interruption.
Original PR description
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is…
### Steps to reproduce - Install `sale_timesheet_enterprise`. - Go to **Tasks → All Tasks**. - Switch to the **Gantt** view. - Group by **Sale Order Item** (`sale_line_id`). ### Issue A traceback is raised when loading the Gantt view with group by `sale_line_id`: ```text ValueError: Invalid field 'planned_hours' on model 'project.task' for 'planned_hours:sum' ``` ### Root cause The Gantt progress bar computation for the `sale_line_id` grouping performs a `_read_group()` aggregation on the `planned_hours` field of `project.task`. However, `planned_hours` was renamed to `allocated_hours` during the saas-16.5 migration, so the former field no longer exists on `project.task`. As a result, the aggregation raises a `ValueError`. Migration reference: https://github.com/odoo/upgrade/blob/e638c6ce00d9d8936d034ad7130fef51565b9195/migrations/project/saas~16.5.1.2/pre-migrate.py#L10 Issued PR: https://github.com/odoo/enterprise/pull/49685 ### Fix Use `allocated_hours`, the renamed equivalent of `planned_hours`, when computing the Gantt progress bar. This restores the Gantt view when grouping tasks by **Sale Order Item** and prevents the traceback. Forward-Port-Of: odoo/enterprise#122994 Forward-Port-Of: odoo/enterprise#122297
This fixes an issue where website content generated through the AI Assistant could disrupt later editing. AI-created snippets now render without extra editor metadata, so users can continue dragging snippets and editing the page normally after saving.
Original PR description
Steps to see the issue: - Open website and start editing - Click on "AI Assistant" button - Ask it to drop a popup - Save the page and start editing again => Snippets aren't droppable and the `#wrap` of the page isn't editable. This happens because snippets inherit branding when they are rendered, so they have `data-oe-id` and others on them, which breaks the usual website flow. This occurs since [1], which added website_id to the context, and in website inherit_branding is set to true automatically, which doesn't happen without the website id. [1]: https://github.com/odoo/enterprise/commit/f9a1c8deeb74749fd176bfc8825c621f214b1985 task-6376299
Several automated tests were corrected so they use valid invoice, tax, product, and AI configurations. This helps prevent false test failures and keeps quality checks aligned with real business rules across support, expenses, manufacturing, purchasing, rentals, and localization flows.
Original PR description
https://github.com/odoo/odoo/pull/274672
The Belgian payroll 274 report now calculates deducted amounts correctly by avoiding double counting of SME exemptions. This helps businesses produce more accurate payroll tax declarations and uses the proper capped amount for the 274.34 report.
Original PR description
Prior to this commit, there was a bug where the deducted amount double counted the SME exempted amount in the 274 report. This commit fixes this.
This fixes Colombian electronic invoice PDF layouts so the company address is no longer pushed out of view when using Folder or Wave designs with long taglines. It also keeps the invoice title from overlapping the QR code, improving the readability and compliance presentation of exported invoices.
Original PR description
Issue: On Wave and Folder layout, the address of the company doesn't appear on invoices. Steps to reproduce: - In a Colombian company, - Set company layout to Folder - Add a long tag line, - Create an invoice, - Send it to DIAN - Export to PDF Current behavior: - Company address is missing in the header Cause: Tag line + logo and address take 100% of the display width. However, loca add a QR code on the left, so it takes QR Code + 100% width. Therefore, address was out of the PDF. Moreover, for Folder layout, some resizing was done and as soon as there was a tag_line, the `rem` was downsized, allowing the invoice title: "Factura Electrónica de Venta SETP/*\*\*/\*\*\*\*" to be displayed entirely. The fix of the previous issue stopped the resizing, then the invoice title got overridden by the QR Code (same as without tag_line before this fix). opw-6239030 Forward-Port-Of: odoo/enterprise#122205 Forward-Port-Of: odoo/enterprise#119678
Field service interventions now require both start and end dates before they can be completed. Send and Publish actions are also hidden when no date is set, helping teams avoid incomplete or incorrectly scheduled work.
Original PR description
After this PR: - Both dates are required to use the 'Complete' action button on an intervention - If the start date is set on an intervention, the end date should be required (and vice versa) - We hide the 'Send' and 'Publish' buttons if there is no date set task-6234939 Forward-Port-Of: odoo/enterprise#123148 Forward-Port-Of: odoo/enterprise#118411
Features or functions removed from Odoo
This change reverses a previous option that allowed users to choose the Stripe operating mode for expense cards. It was removed because selecting the wrong mode could put live Stripe accounts and funds at serious risk, and the feature will be redesigned with safer safeguards.
Original PR description
This reverts commit 48bb5669e8d05c835e3a3db1a1d8889a2cc137f4. The reason for the reversal is the high potential of destroying your live account and locking you out of your account money by mistake. The initial task will be reworked to ensure this case may not happen
Code cleanup and technical improvements
The product catalog integration was updated to match recent platform changes and simplify related customizations. This should make catalog behavior more consistent across manufacturing, field service, rentals, and subscriptions while reducing maintenance effort.
Original PR description
Adapt the catalog uses and overrides to the community changes Improve and clean catalog overrides as well. See odoo/odoo#271273
This change updates Odoo Studio's form editor internals to stay compatible with the next version of the web framework. It should not change day-to-day behavior, and existing tests confirm key form editor displays still work as expected.
Original PR description
Replaced 2 `useLayoutEffect` calls with `useEffect` and `onMounted` because `useLayoutEffect` is deprecated in OWL3. Effect #1 reacted to `viewEditorModel.showInvisible` (a reactive proxy field),…
Replaced 2 `useLayoutEffect` calls with `useEffect` and `onMounted` because
`useLayoutEffect` is deprecated in OWL3.
Effect #1 reacted to `viewEditorModel.showInvisible` (a reactive proxy field), using
the root DOM element only as a guard. Migrated to `useEffect`: reading
`this.viewEditorModel.showInvisible` inside the callback auto-subscribes the effect so
it re-runs on every toggle. To make the root element subscribe the effect on mount,
`useRef("compiled_view_root")` (owl2-compat, untracks the underlying ref signal) was
replaced with `this.rootRef = signal.ref()`, and `form_editor_compiler.js` was updated
to bind the compiled root's `t-ref` to `__comp__.rootRef` so the signal receives the
DOM element at mount time.
Effect #2's only dependency was `[rootRef.el]`; it ran a single time when the DOM was
ready, so `onMounted` is the faithful equivalent.
The `useLayoutEffect` refactored in this PR had test coverage — below are some tests
that failed when the effect was commented out, and are now passing:
- @web_studio/view_editors/form_editor/correctly display hook in form sheet
- @web_studio/view_editors/form_editor/empty form editor
- @web_studio/view_editors/form_editor/invisible form editor
see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2624601/build/116553774This change updates Odoo Studio's internal view-editing components to use the newer supported interface mechanisms. It helps keep Studio compatible with the next framework version while preserving existing editing behavior covered by tests.
Original PR description
Replaced `useLayoutEffect` with `onMounted`/`onPatched` (for the `data-studio-xpath` attribute) and `useListener` (for the click listener) because `useLayoutEffect` is deprecated in OWL3. The…
Replaced `useLayoutEffect` with `onMounted`/`onPatched` (for the `data-studio-xpath` attribute) and `useListener` (for the click listener) because `useLayoutEffect` is deprecated in OWL3. The `useStudioRef` hook previously used `useLayoutEffect` to both set a `data-studio-xpath` attribute on the element and attach a capture-phase click listener. The ref was a string-named compat `useRef`, so its `.el` getter untracks the signal — meaning a reactive `useEffect` would never re-subscribe when the element mounts. For `data-studio-xpath`, `onMounted`/`onPatched` reproduce the "set once el exists, re-apply on element recreation" semantics with synchronous layout timing, which Studio requires because it reads the attribute directly off the DOM. The click listener was initially migrated to `useListener(() => ref(), …)`, but was later converted to `onMounted`/`onPatched`/`onWillUnmount` element-tracking to properly handle the null ref at setup time. As a final step the ref itself was promoted to a native `signal.ref()`, returned by the hook and bound in each consumer template via `t-ref="this.<name>"`. `FieldStudio` reuses the inherited `this.fieldRef` signal (contributed by the companion odoo PR) rather than declaring its own. The useLayoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - @web_studio/view_editors/form_editor/restore active notebook tab after adding/removing an element - @web_studio/view_editors/form_editor/label edition - @web_studio/view_editors/form_editor/many2one field edition see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2624591/build/116553824 Community PR: https://github.com/odoo/odoo/pull/275094
The mobile integration has been reorganized internally while keeping the existing service available for compatibility. This prepares the mobile framework for newer technology changes without changing the expected user experience, including barcode-related mobile flows.
Original PR description
In this commit, we rewrite the mobile service as a plugin. For legacy purposes, we keep the mobile service (as a service). We also adapt the codebase to reflect the changes on the service.
This update modernizes how certain stored values are initialized across accounting, payroll, appointments, helpdesk, ESG, and localization features. It is mainly an internal improvement that should make module setup and upgrades more consistent without changing day-to-day workflows.
Original PR description
https://github.com/odoo/odoo/pull/256914
This update standardizes how internal record values are prepared before being saved, reducing the risk of inconsistent behavior when several records are updated together. It also adjusts related business apps so they continue to handle grouped updates reliably without changing visible workflows.
Original PR description
``Field.write`` calls ``convert_to_cache`` with ``records``, not with a single ``record``. Therefore, ``convert_to_cache`` must return the same value for all records in the recordset. The only exception is ``_RelationalMulti.write``, which does not call ``convert_to_cache``. In that case, ``_RelationalMulti.convert_to_cache`` may depend on each record's current value, so we explicitly assert that ``records`` contains at most one record.
This update reorganizes how relationship field details are defined internally, aligning Enterprise code with a related Community change. It should help keep reporting, AI field tools, and Studio customizations consistent without changing day-to-day user workflows.
Original PR description
Community: https://github.com/odoo/odoo/pull/196498
10 changes
Enhancements to existing features
Odoo can now use official daily exchange rates from the Central Bank of Azerbaijan for automatic currency updates. This helps businesses using AZN translate multi-currency accounting and tax transactions more accurately, including rates quoted for larger nominal amounts.
Original PR description
This commit adds the Central Bank of Azerbaijan (CBA) as a supported service provider for automatic currency rate updates. Purpose: To ensure multi-currency accounting entries and taxable transactions are accurately translated into the national currency (AZN) using the official exchange rate defined by the CBA for the transaction day. Functionality: -Enables fetching official daily exchange rates directly from CBA via XML. -Automatically handles rates defined for different nominal quantities (e.g., rates quoted per 100 units instead of 1 unit). Backport of: https://github.com/odoo/enterprise/pull/122626 task-6112867
Resolved issues and error corrections
The project Gantt view now correctly shades unavailable periods when a user has employees in multiple companies. This keeps visual scheduling cues aligned with time-off warnings, helping planners avoid assigning work during approved absences.
Original PR description
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and…
Steps to reproduce: - Create one user linked to two companies. - Create one employee per company for that user. - Select one company and approve a time off for the employee. - Open Tasks > Gantt and create a task during the approved time-off period the warning is shown and the Gantt cell is grayed out. - Select both companies and create a task during the same time-off period in Tasks > Gantt. Issue: When multiple companies are selected, the time-off warning is still displayed but the corresponding Gantt cells are no longer grayed out, leading to an inconsistency between the warning logic and the Gantt rendering. Cause: In multi-company setups, a user can be linked to multiple resources. The Gantt unavailability logic assumed a one-to-one relationship between user and resource causing unavailability intervals from some resources to be overwritten. Solution: Aggregate unavailability intervals from all resources linked to the same user, limited to the selected companies, and merge them with the company calendar unavailability to ensure consistent Gantt gray rendering. Related PR: https://github.com/odoo/enterprise/pull/57028 task-5089385 Forward-Port-Of: odoo/enterprise#105288
This update fixes an issue in the sales accounting area to improve reliability when working with sales order lines. The limited pull request details do not describe the exact user scenario, but the change is intended to prevent incorrect behavior reported through a support case.
Original PR description
Long description Steps to reproduce: ------------------- * * > Observation: Why the fix: ------------ opw-6290222
This fix prevents an error when users propose adding a step from the Shop Floor for manufacturing orders whose bill of materials contains very similar operations. It makes the improvement suggestion flow more reliable for teams using PLM to update manufacturing instructions.
Original PR description
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback…
[FIX] mrp_workorder_plm: avoid singleton traceback when matching BOM operations **Issue** Adding a step in a manufacturing order with two operations that are too similar could lead to a traceback when proposing an improvement from the Shop Floor. **Steps to reproduce** - Install the Product Lifecycle Management app. - Create a BOM for any product with two operations that: - Have the same name and work center - Have no variant - Create and confirm a Manufacturing Order for that product. - Open the Shop Floor view. - Click the gear icon -> Update Instructions -> Improvement Suggestion -> Add a Step -> Propose a Change. -> A traceback occurs **Cause** When adding a step: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L10 It tries to find the corresponding operation in the ECO's new BoM. This relies on `_get_sync_values()`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_plm/models/mrp_routing.py#L9-L13 Because two operations share the same name, work center, and no variant, both match the filter: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L39 This results in a singleton error when accessing `operation.id`: https://github.com/odoo/enterprise/blob/1c02615b73a2b4fb9f1ab91167a3c8d7c9ac824c/mrp_workorder_plm/models/mrp_workorder.py#L42 opw-6241880 Forward-Port-Of: odoo/enterprise#119404
Users no longer need to be linked to their own employee record to create an expense from a document. They must still have permission to create expenses for another employee, so normal access controls remain in place.
Original PR description
Removes the constraint saying a user has to be linked to an employee to create an expense from a document. In this case, the user still needs the rights to create an expense for another employee. task-6237021 Forward-Port-Of: odoo/enterprise#123523 Forward-Port-Of: odoo/enterprise#118955
Imported Chilean electronic invoices now use the amount in the invoice currency instead of incorrectly applying Chilean peso amounts. This prevents vendor bills in currencies such as UF from being created with wrong totals, reducing accounting corrections and reconciliation issues.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662 Forward-Port-Of: odoo/enterprise#123179 Forward-Port-Of: odoo/enterprise#119664
Duplicating certain Sign templates could fail when the same signer roles appeared across multiple documents and fields. The fix prevents already-processed signer roles from being copied again, allowing affected templates to duplicate successfully.
Original PR description
Issue: This [loop](https://github.com/odoo-dev/enterprise/blob/55bb2cc570451361701d53583f019ed832a5e5d3/sign/models/sign_item.py#L59-L63) runs multiple times with the same approvers(sign.item.role), but doesn't take into account the already 'seen map' inside the base copy function for batching. If they are already seen they will return a non-iterable [None]. To replicate: 1) Sign -> Template -> upload PDF 2) Go into the template 3) Add 2 Documents, with 2 signers and multiple fields on both documents 4) Save -> gear Icon -> make into template 5) Go back to the list view of templates 6) Select the template -> Gear Icon -> Duplicate Fix: add an already seen check to skip if already seen. opw-6352408
Audit checks that are successfully reviewed now refresh the number of invalid records shown in the report. This prevents users from seeing outdated anomaly counts after a check has been corrected, improving confidence in audit reporting.
Original PR description
Problem: Sometimes after an audit check passes (gets reviewed successfully), the count of invalid records in the audit report is not updated. Steps to reproduce: 1. Add a check for an audit cycle 2. Make sure the check's domain is satisified by at least one record 3. Check the audit report and see the check you added 4. The check status should show an anomaly and the count of invalid records will be greater than 0 5. Now, edit the check so that the domain is not satisfied by any record 6. Check the audit report again and see the check you edited 7. The check status should show "Reviewed" but the count of invalid records will still be greater than 0, which is not correct Cause: When updating the status of an audit check, the count of invalid records is not updated, only the status gets updated. opw-6264177
Kenyan POS refunds can now be validated without triggering an error during eTIMS processing. The fix also improves handling when multiple offline orders are synchronized together, helping keep sales and refund workflows running smoothly.
Original PR description
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised…
Steps to reproduce: 1. Install `l10n_ke_edi_oscu_pos`, set company to Kenya. 2. Sell and validate an order. 3. Refund it from the POS and validate the refund order. Issue: - A traceback is raised when validating the refund: `ValueError: Expected singleton: pos.order(<refund>, <original>)` raised in `get_l10n_ke_edi_oscu_pos_data`. Cause: - When syncing a refund, `sync_from_ui` returns both the new refund order and the original refunded order. `waitForPushOrder` forces post-processing for every Kenyan order in that list, so `beforePostPushOrderResolve` receives both ids in `order_server_ids` and forwards them as-is to `action_post_order` and `get_l10n_ke_edi_oscu_pos_data`, both of which expect a single record. `action_post_order` fails the same way, but its error was silently swallowed by the surrounding try/catch, letting the traceback surface only on the second call. - The same multi-id list is also produced whenever several orders created offline get synced together once back online. Solution: - `get_l10n_ke_edi_oscu_pos_data` is only needed for the receipt of the order being validated, so call it with `order.id` instead of the full `order_server_ids` list. - Replace the `action_post_order` call with `action_post_selected_orders`, which posts each order individually and skips ones already sent to eTIMS, correctly handling both the refund case (original order is already `sent`) and the offline multi-order sync case. opw-6364221
Invoice tax recalculations using Avatax now refresh the pre-tax base amount instead of keeping an outdated value. This helps prevent invoices from remaining stuck with incorrect tax totals after recomputing taxes or reconfirming a draft invoice.
Original PR description
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of.…
Issue: Invoice lines have a json field, `extra_tax_data`. The `extra_tax_data` can include a `manual_total_excluded_currency` value, which is the pre-tax base amount that taxes get added on top of. In some cases, the `manual_total_excluded_currency` value can end up incorrect (cause unknown). When this occurs, clicking "Compute Taxes" or resetting the invoice to draft and reconfirming does not correct the problem. This leaves the invoice in a persistently incorrect state with no straightforward way to fix it. Explanation: The bug is in `_process_external_taxes` in the `account_external_tax_mixin.py` in the `account_external_tax` module. During tax re-computation, if `extra_tax_data` is considered still valid, it is used to populate an in-memory base line dict. In this dict, `manual_tax_amounts` (which comes from a sub-dict in `extra_tax_data`) is explicitly cleared and fully repopulated from the fresh Avatax response every time. However, `manual_total_excluded_currency` in the base line dict is only updated if it is `None`. So, if it has an positive incorrect value, it will not be updated using the fresh Avatax response. Then, it will be written back to `extra_tax_data` unchanged, perpetuating the problem. Solution: Reset `manual_total_excluded_currency` to `None` at the start of each re-computation loop, mirroring what is already done for `manual_tax_amounts`. This ensures the pre-tax base amount is always taken from the current Avatax response rather than a previous value. This makes the behavior of `manual_tax_amounts` and `manual_total_excluded_currency` consistent with each other. opw-6235597
3 changes
Resolved issues and error corrections
This update makes Odoo’s stdnum integration accept additional options when creating a SOAP client. It improves compatibility with external services that require extra connection settings, reducing the chance of integration errors.
Original PR description
Added support for additional keyword arguments in stdnum's new_get_soap_client function. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a task is moved to another project, follower notification preferences are now updated to match the new project’s settings. This prevents people from missing important task updates after a task is reassigned between projects.
Original PR description
Steps to reproduce: - 1. Create projects A and B. 2. Add a user as a follower of project B and select specific notification subtypes (e.g., 'Stage Changed'). 3. Create a task in project A and add the same user as a follower(defaulting to 'Discussions'). 4. Move the task from project A to project B. Issue: - The follower's subscription preferences on the task do not reflect their project-level settings after the move. In the example above, the user remains subscribed only to 'Discussions' and misses 'Stage Changed' updates. Cause: - The default auto-subscription logic skips existing followers. When moving a task, this prevents the system from adding the new project's notification preferences to users who were already following the task. Fix: - Override `_message_auto_subscribe` in project.task to the `update` policy when the `project_id` is changed. task-5877507 Forward-Port-Of: odoo/odoo#248224
This change ensures each project dashboard only shows the sales order lines that belong to that specific project. It prevents sales and profitability figures from being inflated by lines from other projects, so the dashboard data is more accurate.
Original PR description
Steps to reproduce: ------------------------- 1. Install sale_project and accounting 2. Create two billable projects with specific analytic accounts 3. Create two service products with "prepaid/fixed…
Steps to reproduce: ------------------------- 1. Install sale_project and accounting 2. Create two billable projects with specific analytic accounts 3. Create two service products with "prepaid/fixed price", set "create on order" to "Task" and assign each product to its respective project in the project column 4. Create a SO with these products and confirm it 5. Click on the projects stat button (it shows two projects) Observation: ------------------ Both project dashboards display both SOLs even though each SOL belongs to a different project's analytic account, leading to incorrect SOL count and profitability calculation. Cause: --------- https://github.com/odoo/odoo/blob/281658e86971687656f3235ac1ff8afcb52f2908/addons/sale_project/models/project_project.py#L420-L427 The domain matched SOLs via `order_id,` which pulled all SOLs from a matched order regardless of which project they belonged to. Solution: ----------- Add an additional filter on analytic_distribution to ensure SOLs with no `project_id` are only included when their analytic account matches the project's analytic account, preventing cross-project SOL leakage. opw-6205750 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr