Daily updates from Odoo
Monday, June 22, 2026
74 changes · saas-19.2
New functionality added to Odoo
This update introduces support for several new food delivery providers – including Talabna, Mandoob, and DiDi Food – expanding Odoo's capabilities for restaurants and delivery services. The addition of these providers, along with backports of existing ones, broadens Odoo's reach to support diverse regional markets and customer needs.
Original PR description
In this commit: - We are introducing new delivery providers like Talabna, Mandoob, Snoonu, DiDi Food and Zyada for different countries and backporting Radyes, ToYou, The Chefz, InstaShop and Smiles. Task-6263289,6263272,6263203,6263165,6310690 Forward-Port-Of: odoo/enterprise#121051 Forward-Port-Of: odoo/enterprise#119537
Enhancements to existing features
This update improves the payment process by adding debtor and creditor information to the data sent to Odoofin, which is required for initiating payments through Powens and Saltedge. This change ensures smoother and more complete payment initiation workflows. It's a necessary improvement for supporting key payment integrations.
Original PR description
In order to be able to initiate payments using Powens and Saltedge, we need to include debtor information in the payload sent to Odoofin. This commit adds the necessary fields and updates the tests accordingly. Task ID: 5977148, 6095729 Forward-Port-Of: odoo/enterprise#119843
This update standardizes the font style for customer notes in the Point of Sale system to align with the appearance of line customer notes. This enhances visual consistency and improves the overall user experience for customers and staff.
Original PR description
We updated the general customer note font to match the line customer note's one. task-6294200
Resolved issues and error corrections
This fix resolves an issue preventing the 'Send to SII' option from appearing on Chilean vendor bills. The update adjusts internal code to correctly display this button when a DTE is generated, ensuring invoices can be properly transmitted to the SII (Servicio de Impuestos Internos) as required by Chilean regulations. This improves compliance and streamlines the invoicing process.
Original PR description
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF…
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF [XML](https://www.odoo.com/mail/message/1097235975) file. * Create a new **Purchase Journal** with **Use Documents** enabled. * Create a vendor bill using this journal. * Set the **Document Type** to **46 - Liquidación-Factura Electrónica**. * Confirm the vendor bill. **Observed behavior:** * The Send button is not visible on the confirmed vendor bill despite the DTE being generated and `l10n_cl_dte_status` being set to `not_sent`. **Cause:** * `_compute_display_send_button` in `account` only returns `True` for sale documents (`is_sale_document()`), so the "Send" button — which opens the Send & Print dialog containing the "Send to SII" option — was never shown on vendor bills. * `_get_move_constraints` in `account.move.send` unconditionally adds a `not_sale_document` constraint for non-sale documents, blocking the Send & Print dialog from processing vendor bills even if the button were visible. * The cron's `cron_run_sii_workflow` only processes moves with `l10n_cl_dte_status = 'ask_for_status'`, skipping moves still in `not_sent` state. **Fix:** * Override `_compute_display_send_button` in `l10n_cl_edi` to also show the "Send" button on posted moves with `l10n_cl_dte_status == 'not_sent'`, matching the pattern used by `l10n_br_edi`. * Override `_get_move_constraints` in `l10n_cl_edi` to remove the `not_sale_document` constraint for Chilean purchase documents with `not_sent` status, matching the pattern used by `l10n_br_edi`. **REF** During this [refactor](https://github.com/odoo/enterprise/pull/103427/changes/f5617ecf7584cf019897408df94b002622f48d9d), these two methods were inadvertently missed and were not overridden opw-6300571
This update resolves a test failure related to GCC POS localization reporting. The fix ensures that order receipts display the correct information and addresses assertions related to rounding and discounts. This improves the reliability of the GCC POS test suite.
Original PR description
- Fixed `TestGenericGCC.test_generic_localization` which was failing because some information was not rendered on the order receipt. - Added rounding configuration to the POS config so that the assertion for `Rounding` does not fail. - Added steps for `Discount` and `Change` in `generic_localization_tour` so that the assertions for `Discount` and `Change` do not fail. Error-237988 Task-5897376 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a crash that occurred when users manually corrected bank statement lines within the Odoo Enterprise system. The issue stemmed from a missing context key during record creation, leading to incorrect journal assignments. This fix ensures bank statement lines are created with the correct journal, preventing data inconsistencies and system instability.
Original PR description
When the manual correction tool was used to fill in the lines, we weren't passing the active context when creating the new records. In the case of bank statements, it could be an issue as the `default_journal_id` key is expected to be present to set the correct journal on the newly created bank statement line. Without this key in the context, it would default to the first journal with a valid type (see function `_search_default_journal`). If the journal found this way didn't match the current journal, a crash would occur when modifying the newly created lines. opw-[6294117](https://www.odoo.com/odoo/unassigned-tasks/6294117) Forward-Port-Of: odoo/enterprise#121032 Forward-Port-Of: odoo/enterprise#120745
This update corrects a previous issue where fully settled customers with past pay-later payments were incorrectly prevented from seeing their Customer Statements. The fix now checks for any past pay-later payment lines, ensuring the statement button appears regardless of whether the customer's total balance is zero. This improves the user experience for all customers.
Original PR description
The override of _compute_has_moves was checking `total_due != 0` to set `has_moves` on for PoS pay_later customers. Once the customer is fully settled however, `total_due` is 0 and the check does not pass anymore, so `has_moves` goes back to `False` and the Customer Statement button hides for them, even though they had past pay_later payment lines. The fix is to check directly for any past pay_later `pos.payment` instead, which covers the cases where partner had used pay_later payment methods before, regardless if they have settled their total due or not. opw-6173760 Forward-Port-Of: odoo/enterprise#120911 Forward-Port-Of: odoo/enterprise#116536
This update resolves an issue where sending NFC-e invoices through IAP would halt the POS synchronization process when IAP credits were exhausted. The change prevents the system from blocking POS updates, ensuring smoother operations when IAP credit limits are reached. This improves reliability and prevents disruptions to sales workflows.
Original PR description
When sending an NFC-e, tax calculation is done by calling Avatax through IAP. If the IAP account has no credits left, iap_jsonrpc() raises an InsufficientCreditError. opw-6290857 Forward-Port-Of: odoo/enterprise#120700
This update resolves an error that prevented users from sending SMS messages to website visitors. The change updated how the system accesses visitor phone numbers, ensuring compatibility after a recent data restructuring. This ensures the SMS functionality works correctly for all visitors.
Original PR description
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another…
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another `Form` block. - Configure the form action to `Create an Opportunity` and `save`. - Fill in the required fields, including phone number and `Submit` the form. - Go to `Website` > `Reporting` > `Visitors` and click the `SMS` button on the visitor record. `AttributeError: 'website.visitor' object has no attribute 'phone'` After [this commit], which removed the mobile field from res.partner along with all related views, then it was updated to access the phone number from the website visitor. When a user creates an opportunity through the website and then tries to send an sms from the corresponding visitor record, it raises an error [1] because it attempts to access the phone field on website.visitor. when an anonymous (non-logged-in) user creates an opportunity, clicking the sms button on the corresponding visitor record triggers error here [2]. This commit ensures that the correct mobile field is accessed from the website visitor. [this commit]: https://github.com/odoo/odoo/commit/6b820eb6fc6f782ba6a83d605d87b4a1dd2a87be [1]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L13 [2]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L20 sentry-7550340909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270118
This update resolves an issue where text entered into a SelectMenu field was intermittently being cleared, causing data entry problems. The fix ensures the input field accurately reflects user input during asynchronous data updates, improving data accuracy and user experience. It also corrects a related issue with the SelectMenu clearing when empty.
Original PR description
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all…
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all the typed characters Issue: - It's randomly removing characters, for example, type "1234567890" and observe Cause: - SelectMenu updates its internal searchValue only inside the debounced onInput handler `debouncedOnInput`. When an autocomplete callback reloads choices before that debounce fires, the component rerenders with a stale searchValue and writes that outdated value back into the controlled input, overwriting newer characters already typed by the user. Solution: - Update searchValue immediately on every raw input event and keep only the search callback debounced. - Also reset searchValue to null when a required single-select is blurred while empty, so the input falls back to the selected choice label instead of staying visually cleared. opw-6000540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267974 Forward-Port-Of: odoo/odoo#255819
A bug preventing users from adding cover images to Knowledge articles has been resolved. The issue stemmed from a missing callback function during the upload process, causing the upload to fail. This update ensures cover images can now be successfully added, improving the article creation experience.
Original PR description
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback:…
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback: `Uncaught Promise > this.props.setAbortUploadsCallback is not a function` Cause: - `KnowledgeCoverSelector` extends the html_editor `ImageSelector`, whose upload flow registers an abort callback through setAbortUploadsCallback. The generic MediaDialog provides this callback, but KnowledgeCoverDialog renders KnowledgeCoverSelector directly and did not pass it. As a result, the inherited upload flow called a missing prop. Solution: - Pass setAbortUploadsCallback from KnowledgeCoverDialog to KnowledgeCoverSelector and abort pending uploads when the cover dialog is discarded. Alternative approach: - Make ImageSelector tolerate callers that do not provide setAbortUploadsCallback by calling it with optional chaining. opw-6176716 Forward-Port-Of: odoo/enterprise#120467 Forward-Port-Of: odoo/enterprise#116906
This update resolves an issue where users with limited accounting permissions couldn't properly reconcile bank statements, leading to invoices being incorrectly marked as fully paid. The fix ensures accurate reconciliation by safely bypassing a permission check during the automated process, maintaining data auditability and preventing incorrect Account Receivable line additions.
Original PR description
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only…
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only "Invoicing & Banks" rights tries to reconcile a Bank Statement with the same partner, amount, and the invoice name as the memo, the automatic reconciliation fails to properly match the payment Instead, the invoice is incorrectly considered as Fully Paid with an unwanted extra Account Receivable line added ### Cause When a new Bank Statement is created, `_try_auto_reconcile_statement_lines()` is called and matches the outstanding credit, which invokes `set_line_bank_statement_line()` In 19.0, this function creates a balancing line and triggers `move._compute_checked()` to update dependencies Especially `_compute_is_reconciled` But checked as been replaced by `review_state` This FW port will use an update on the `review_state` instead of the `checked` A user with "Invoicing & Banks" rights lacks the `account.group_account_user` group, meaning the move is not marked as `reviewed`, preventing dependencies from computing correctly Consequently, the statement line's `amount_residual` is not cleared and the line is not removed from `remaining_st_line_ids` Later in the process, `_try_auto_reconcile_statement_lines()` is called again with `with_user(SUPERUSER_ID)` Because the payment matching was never finalized in the previous step, the engine fallback matches against the full invoice, adding an incorrect Account Receivable line to close it ### Steps to reproduce - Install `accountant` - Go to Accounting / Configuration / Accounting / Journals - Open the Bank, under Incoming Payments tab, set the Manual Payment method's Outstanding Receipts account to 101403 Outstanding Receipts - Update the Demo user's accounting rights to Invoicing & Banks - Log in with the Demo user - Create and confirm an invoice for Acme Corporation (Amount: $1100) - Register a payment on the invoice (Amount: $500, Keep open) - Copy the invoice name - Open the Bank Reconciliation widget from the Accounting Dashboard - Create and add a new Bank Statement Line (Label: Invoice name, Partner: Acme Corporation, Amount: $500) Before the fix, an unexpected Account Receivable line is created and the invoice is marked as Fully Paid ### Notes Instead of processing the entire block under SUPERUSER_ID, which would hide the creator identity in logs and chatter, the context key `skip_account_review_check=True` is injected during the automated statement line reconciliation This safely bypasses the group check inside `_is_user_able_to_review` for this specific automated flow A fallback using `.with_user(SUPERUSER_ID)` is already implemented twice within the same `_try_auto_reconcile_statement_lines` method for this specific use case, but avoiding it here preserves data auditability opw-6077137 Forward-Port-Of: odoo/odoo#270080
This update resolves an issue where users with restricted accounting rights incorrectly marked invoices as fully paid, leading to incorrect Account Receivable entries. The fix ensures automatic bank reconciliation works correctly for these users by safely bypassing a group check during the reconciliation process, maintaining data auditability.
Original PR description
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only…
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only "Invoicing & Banks" rights tries to reconcile a Bank Statement with the same partner, amount, and the invoice name as the memo, the automatic reconciliation fails to properly match the payment Instead, the invoice is incorrectly considered as Fully Paid with an unwanted extra Account Receivable line added ### Cause When a new Bank Statement is created, `_try_auto_reconcile_statement_lines()` is called and matches the outstanding credit, which invokes `set_line_bank_statement_line()` This function creates a balancing line and triggers `move._compute_checked()` to update dependencies However, `move.checked` requires `_is_user_able_to_review()` to be True A user with "Invoicing & Banks" rights lacks the `account.group_account_user` group, meaning the move is not marked as checked, preventing dependencies from computing correctly Consequently, the statement line's `amount_residual` is not cleared and the line is not removed from `remaining_st_line_ids` Later in the process, `_try_auto_reconcile_statement_lines()` is called again with `with_user(SUPERUSER_ID)` Because the payment matching was never finalized in the previous step, the engine fallback matches against the full invoice, adding an incorrect Account Receivable line to close it ### Steps to reproduce - Install `accountant` - Go to Accounting / Configuration / Accounting / Journals - Open the Bank, under Incoming Payments tab, set the Manual Payment method's Outstanding Receipts account to 101403 Outstanding Receipts - Update the Demo user's accounting rights to Invoicing & Banks - Log in with the Demo user - Create and confirm an invoice for Acme Corporation (Amount: $1100) - Register a payment on the invoice (Amount: $500, Keep open) - Copy the invoice name - Open the Bank Reconciliation widget from the Accounting Dashboard - Create and add a new Bank Statement Line (Label: Invoice name, Partner: Acme Corporation, Amount: $500) Before the fix, an unexpected Account Receivable line is created and the invoice is marked as Fully Paid ### Notes Instead of processing the entire block under SUPERUSER_ID, which would hide the creator identity in logs and chatter, the context key `skip_account_review_check=True` is injected during the automated statement line reconciliation This safely bypasses the group check inside `_is_user_able_to_review` for this specific automated flow A fallback using `.with_user(SUPERUSER_ID)` is already implemented twice within the same `_try_auto_reconcile_statement_lines` method for this specific use case, but avoiding it here preserves data auditability opw-6077137 Forward-Port-Of: odoo/enterprise#120217 Forward-Port-Of: odoo/enterprise#118023
This update resolves an issue where milestone deadline dates would disappear from task views after navigating back or refreshing. The fix ensures that milestone deadlines are consistently displayed in task Kanban cards and headers, regardless of user navigation, improving project tracking accuracy.
Original PR description
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4.…
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4. Click the browser's back button (or simply refresh the page while on the task kanban view). Issue: Milestone deadline dates disappear from the task Kanban cards and headers after navigating back or reloading. Why this happens: When hitting the browser back button or refreshing, the web client's router state recovery workflow executes (`loadRouterState` -> `loadState` -> `doAction` -> `_executeActWindowAction`). During this flow, `_getActionParams` checks if it can reuse the cached `lastAction`. However, due to a safety condition introduced in commit ab26f95893 to prevent embedded action showing across different projects, the router falls back to generating a fresh action request via `state.action`. This forces `_loadAction` to fetch the action definition from the database. Because the original base action window `act_project_project_2_project_task_all` lacks the `display_milestone_deadline` key inside its default context dictionary, the reloaded view is rendered without the flags required by the frontend to display milestone deadlines. opw-6283514 Forward-Port-Of: odoo/odoo#269781
This update prevents logged-in users from attempting to sign up or log in through the website's signup page. Previously, users could submit the form, resulting in an error. Now, a warning message appears, and the button is disabled, ensuring only new users can register.
Original PR description
Steps to reproduce: 1.Log in to the backend as an Admin (or any authenticated user). 2.Navigate to Website -> Configuration -> System Pages and open the Signup page. 3.Fill in the signup form and submit it. 4.After successfully signing up, click the Logout button. 5.Observe that a "405 Method Not Allowed" error is displayed. Before this commit: When an already logged-in user accessed the signup page through the System Pages menu and submitted the signup form, clicking the Logout button afterward resulted in a 405 Method Not Allowed error. After this commit: When an already logged-in user accesses the signup or login page, a warning message is displayed and the Sign Up or Log In button is disabled, preventing the form from being submitted. task-6023075 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263791
This update clarifies timesheet reporting by changing the automated rule (AW Rule) to display the name of the GitHub pull request instead of its ID. This provides users with more context, making it easier to link pull requests to the relevant projects and tasks within the Timesheets Assistant.
Original PR description
Before this commit, the AW Rule used in Timesheets Assistant will display the id of the Github Pull request and the repository but that information is not always clear for the user to know which project/task is related to that PR. This commit changes the AW rule for Github to display the name of the pull request instead to have more context to easily match the project/task to the event created by that rule. task-6306166
This update improves the speed of queries related to document access permissions, specifically for the 'my/counters' route which is frequently used. By switching to a subquery, the system now utilizes an index more effectively, resulting in a significant reduction in query response times for portal and internal users.
Original PR description
The '/my/counters' route is hit a lot of times on big databases like odoo.com One thing it does is a `self.env['documents.document].search_count([])` With this commit, we use a subquery for the…
The '/my/counters' route is hit a lot of times on big databases like odoo.com
One thing it does is a `self.env['documents.document].search_count([])`
With this commit, we use a subquery for the folder access instead of the current LEFT JOIN.
This ok since the number of folders is typically small compared to regular documents and the query is fast since it can use the index on 'type'
Before as portal user
------
2x Seq Scan
```
Aggregate (cost=1900290.73..1900290.74 rows=1 width=8) (actual time=282.271..282.276 rows=1 loops=1)
Buffers: shared hit=66629
-> Hash Left Join (cost=41649.94..1900044.55 rows=98472 width=0) (actual time=184.202..282.267 rows=3 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 6) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 6))) OR (((documents_document.access_via_link)::text = ANY ('{edit,view}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 6) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 6)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 28085
Buffers: shared hit=66629
-> Seq Scan on documents_document (cost=0.00..1857903.54 rows=187073 width=26) (actual time=0.022..109.288 rows=28088 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 342576
Buffers: shared hit=33313
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=2)
Buffers: shared hit=6
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=2)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=6
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
-> Hash (cost=37016.64..37016.64 rows=370664 width=16) (actual time=164.521..164.521 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 17824kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=16) (actual time=0.005..100.491 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.002..0.003 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=69
Planning Time: 1.708 ms
Execution Time: 282.344 ms
```
After as portal user
-----
Only 1x Seq Scan
```
Aggregate (cost=2004948.33..2004948.34 rows=1 width=8) (actual time=116.161..116.165 rows=1 loops=1)
Buffers: shared hit=37942
-> Seq Scan on documents_document (cost=145660.16..2004490.36 rows=183187 width=0) (actual time=24.635..116.155 rows=3 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 370661
Buffers: shared hit=37942
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145625.73 rows=13772 width=4) (actual time=11.688..11.689 rows=0 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))))
Rows Removed by Filter: 28198
Buffers: shared hit=4629
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.002..0.002 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.001..0.002 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=56
Planning Time: 1.544 ms
Execution Time: 116.216 ms
```
Before as internal user
--------
```
Aggregate (cost=1902165.43..1902165.44 rows=1 width=8) (actual time=332.919..332.925 rows=1 loops=1)
Buffers: shared hit=69223 read=370
-> Hash Left Join (cost=41649.94..1901908.04 rows=102955 width=0) (actual time=176.179..332.325 rows=10040 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 1054906) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 1054906))) OR (((documents_document.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document.company_id = 1) OR (documents_document.company_id IS NULL))) OR (((documents_document.access_via_link)::text = ANY ('{view,edit}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 1054906) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 1054906))) OR (((documents_document__folder_id.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document__folder_id.company_id = 1) OR (documents_document__folder_id.company_id IS NULL)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 27228
Buffers: shared hit=69223 read=370
-> Seq Scan on documents_document (cost=0.00..1859756.86 rows=190950 width=35) (actual time=15.029..155.718 rows=37268 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 333396
Buffers: shared hit=33931 read=370
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.155..7.920 rows=148 loops=2)
Buffers: shared hit=1612 read=370
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.110..3.448 rows=200 loops=2)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=192 read=190
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.022..0.022 rows=1 loops=400)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=1420 read=180
-> Hash (cost=37016.64..37016.64 rows=370664 width=25) (actual time=157.822..157.823 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 21336kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=25) (actual time=0.005..96.730 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..0.372 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.005..0.078 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=69 read=8
Planning Time: 2.116 ms
Execution Time: 333.013 ms
```
After as internal user
--------
```
Aggregate (cost=2006950.17..2006950.18 rows=1 width=8) (actual time=157.117..157.121 rows=1 loops=1)
Buffers: shared hit=39918
-> Seq Scan on documents_document (cost=145798.74..2006482.26 rows=187165 width=0) (actual time=16.595..156.590 rows=10040 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 360624
Buffers: shared hit=39918
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..1.016 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.012..0.262 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.004..0.004 rows=1 loops=200)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145763.43 rows=14124 width=4) (actual time=0.429..14.916 rows=4625 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))))
Rows Removed by Filter: 23573
Buffers: shared hit=5617
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.007..0.390 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.003..0.074 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=56
Planning Time: 1.569 ms
Execution Time: 157.171 ms
```
portal user
before https://explain.dalibo.com/plan/e1e755fg7bb26a21
after https://explain.dalibo.com/plan/hb5fa1d201ff164g
internal user with few documents access
before https://explain.dalibo.com/plan/f753bf2aa244dg63
after https://explain.dalibo.com/plan/538dg5ecb120ch84
internal user with *lots* of documents access
before https://explain.dalibo.com/plan/cf76h84537f7ge4a
after https://explain.dalibo.com/plan/45317a5e3168c5bcThis update resolves an issue preventing the correct export of balance sheet data in the Lu (Luxembourg) localization. The system now automatically includes a default start date (beginning of the fiscal year) in the XML file, ensuring accurate reporting. This prevents errors during the export process.
Original PR description
Steps to reproduce: - setup a LU company - go to balance sheet - export the xml file - validate the wizard -> Traceback, because the code expects the options to contain the date_from, which is no longer the case since 19.2 as the balance sheet has by default only a date_to. The solution is therefore to define it for the export to the beginning of the fiscal year.
This update corrects a technical issue in the UBL BIS3 generation process for Debit Notes. Previously, the system incorrectly used 'LegalMonetaryTotal' instead of the required 'RequestedMonetaryTotal' node, leading to errors in UBL file creation. This change ensures compliance with BIS3 standards for Debit Note UBL exports.
Original PR description
Problem --------- Debit note should have the node `RequestedMonetaryTotal` instead of `LegalMonetaryTotal`. Solution --------- Add a conditional depending on the document type. opw-6295897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270238
This update resolves an issue in the Data Recycle app where record IDs were incorrectly summed and displayed alongside group names, causing truncation and unreadability. The fix removes the unnecessary aggregation of record IDs, resulting in a cleaner and more informative display of grouped records.
Original PR description
## Issue In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="720" height="281" alt="115492" src="https://github.com/user-attachments/assets/567902af-b356-4a0a-8b1e-2ed101a2eba3" />
## Steps to reproduce
1. Install *Data Recycle* (`data_recycle`)
2. In Data Cleaning > Configuration > Recycle Records, create a new rule:
- Any name
- Model: *Contact*
- Filter: *Name contains G* (or anything else that matches some records)
4. Click the *Run Now* button in the upper left corner
5. In Data Cleaning > Recyle Records, group the records by any field (e.g., *Model*)
6. **The name of the group (Contact) is truncated, making it and the record count unreadable. This is due to the sum of Record ID being displayed in the same row, even though that information is irrelevant.**
## Cause
Similarly to related enterprise PR https://github.com/odoo/enterprise/pull/115492, the *Record ID* field of the `data_recycle.record` model uses the default `sum` aggregator.
https://github.com/odoo/odoo/blob/6de867f1c92bacedc0574b63e9e6a2a57fe805dd/addons/data_recycle/models/data_recycle_record.py#L17
related: https://github.com/odoo/enterprise/pull/115492
opw-6219824
Forward-Port-Of: odoo/odoo#265163This update resolves an issue in the Data Cleaning app where record IDs were incorrectly summed and displayed alongside group names, leading to truncated names and inaccurate counts. The fix removes the automatic summing of IDs in grouped list views, ensuring that group names and counts are displayed correctly.
Original PR description
## Issue In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="709" height="374" alt="6166623-before" src="https://github.com/user-attachments/assets/9d80b1ec-49c0-4b7f-8c6e-53846f9e433e" />
## Steps to reproduce
1. Install *Data Cleaning* (`data_cleaning`)
2. In Data Cleaning > Configuration > Field Cleaning, create a new rule (or edit an existing one):
- Any name
- Model: *Contact*
- Rule:
- Field to Clean: *Name (Contact)*
- Action: *Set Type Case* - Case: *All Uppercase*
4. Click the *Clean* button in the upper left corner
5. In Data Cleaning > Field Cleaning, group the records by any field (e.g., *Field*)
6. **The name of the group (_Name (Contact)_) is truncated, making it and the record count unreadable. This is due to the sum of _Record ID_ being displayed in the same row, even though that information is irrelevant.**
## Cause
The *Record ID* (`res_id`) field is an Integer field defined [here](https://github.com/odoo/enterprise/blob/3603afdd5c0d19c9276f3855156be4040ab5717d/data_cleaning/models/data_cleaning_record.py#L20). By default, Integer fields have the `sum` aggregator:
https://github.com/odoo/odoo/blob/681610c002a310f1c73fc2e5bec8d3dae27bc4a7/odoo/orm/fields_numeric.py#L17-L23
This causes the IDs to be summed up and appear in the group headers.
## After
<img width="740" height="370" alt="6166623-after" src="https://github.com/user-attachments/assets/a42d8f58-06dc-4308-8b6f-1ab09e8034f8" />
related: https://github.com/odoo/odoo/pull/265163
opw-6166623
Forward-Port-Of: odoo/enterprise#115492This update fixes an issue where product costs weren't consistently converted to the POS currency during product loading. Previously, product costs were stored in separate currencies, leading to potential inaccuracies in sales calculations. This change ensures all product costs are correctly converted, improving the reliability of pricing in the Point of Sale system.
Original PR description
When loading products in the POS, both the sale price and the cost were converted to the POS currency using `currency_id`. However a product stores its sale price and its cost in two potentially different currencies: `currency_id` (company currency, falling back to the main company) and `cost_currency_id` (company currency, falling back to the current company). opw-6297452 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269829
This update prevents a popover error that occurred when users clicked on notification envelopes in the chatter. The issue stemmed from a missing `res_partner_id` field, which caused a comparison error. This fix ensures notifications display correctly for all users, regardless of whether a partner ID is available.
Original PR description
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When…
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When clicking on the enveloppe, we display the `message_notification_popover` that calls `isFollowerNotification` to filter follower notifications from other ones. This function compares the ids of the followers of the notification to it's res_partner_id : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/static/src/core/common/notification_model.js#L101-L105 But in our case res_partner_id is undefined because it is not a required field and it will not be set in the case of mass_mailing : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/models/mail_notification.py#L23-L27 opw-6178443 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265263
This update fixes an issue where preparation prints weren't showing all items after transferring an order to a shared table. Previously, only the items on the destination table were printed. Now, when orders are merged, the preparation prints accurately reflect all items from both orders, ensuring accurate kitchen workflows.
Original PR description
When moving an order (Order A) to a table that already has an order (Order B), the merged order only reprints Order B's products. The products from Order A are missing from the preparation reprint.…
When moving an order (Order A) to a table that already has an order (Order B), the merged order only reprints Order B's products. The products from Order A are missing from the preparation reprint. Steps to reproduce: ------------------- * Open a POS session on a Restaurant POS * Create an order (Order A) for Table 1 * Create a second order (Order B) for Table 2 * Transfer/Merge Order A to Table 2 * Reprint the preparation order > Observation: Only the products that were already on Table 2 (Order B) appear on the reprint. Products from Order A are missing. Why the fix: ------------ mergeOrders correctly transfers kitchen history (last_order_preparation_change.lines) via handlePreparationHistory, but does not update uiState.lastPrints on the destination order. The reprint button uses lastPrints.at(-1) when there are no pending changes, so it only shows the destination order's last print batch — ignoring the merged lines entirely. Implementation: After the merge loop, build a consolidated lastPrints entry from the destination order's last_order_preparation_change.lines (which now contains lines from both orders) and push it onto destOrder.uiState.lastPrints so that reprint reflects the full merged state. opw-6060684 Forward-Port-Of: odoo/odoo#270311 Forward-Port-Of: odoo/odoo#256309
This update optimizes how Odoo searches for documents, specifically addressing a complex query that slowed down searches for documents not marked as 'SHARED'. This change aligns with the performance practices used in our production database, resulting in faster and more efficient document searches for users. It’s a performance improvement focused on the Documents module.
Original PR description
Searching for "not 'SHARED'" results in a very complex query. Our own production DB prefers this implementation, also easier to read. credit: https://github.com/odoo/enterprise/pull/105915#discussion_r2745148099 Task-5893183 Forward-Port-Of: odoo/enterprise#120870
This update fixes an issue where the Luxembourg eCDF XML export incorrectly reported financial year data. The change removes a problematic account mapping, ensuring the exported data aligns with the Odoo Profit & Loss view. This improves data accuracy for reporting to the Luxembourg tax authority.
Original PR description
Issue: Users reported that the financial year result in the XML export for the Luxembourg eCDF platform is incorrect, despite being correct in the Odoo Profit and Loss visualization. The exported XML populated incorrect amounts in cell 0161 under certain circumstances (namely, in the case of an explicit entry from account 999999 to account 142000). Solution: * Removed account 142 entirely from both the `ACCOUNTS_2019` and `ACCOUNTS_2020` dictionaries so it no longer auto-populates cells 0161/0162 (up to 2019 included) and 2955/2956 (from 2020 onward). * Removed the 2019 threshold condition in the loop bypass for account 142. * Removed the hard-coded manual pop for cell 2955 since it has been removed from the mapping. * Deleted the redundant reassignment of `net142` in the loss calculation block. Ticket [link](https://www.odoo.com/odoo/project.task/6059571) opw-6059571 Forward-Port-Of: odoo/enterprise#121010
This update resolves a problem where the PDP identifier field in the company registration process was left blank when using non-0225 PEPPOL EAS. It now displays a user error if an invalid identifier is entered, preventing incorrect registrations. This ensures accurate PDP registration and compliance.
Original PR description
Currently when the company partner uses non 0225 peppol EAS the `pdp_identifier` field is `False`. Thus the (related) identifier field on the registration wizard is left empty. Also add a UserError when writing an invalid identifier to the `pdp_identifier` field instead of just silently failing. That way an error ill pop up in the registration wizard when trying to register with an invalid identifier. task-6307489 Forward-Port-Of: odoo/odoo#270915 Forward-Port-Of: odoo/odoo#270330
This update strengthens Odoo's security by ensuring users only have read access to data. This prevents potential issues and unexpected behavior within the system, contributing to a more stable and reliable platform. The change was implemented as a fix to a vulnerability.
Original PR description
Ensure that the user has read access to prevent any unexpected behavior. Task-6226863 Forward-Port-Of: odoo/odoo#267709
A recent upgrade to Odoo 19.2 caused an error when accessing the partner website page. This was due to a change in how website templates are structured. This fix updates the system to align with the new template structure, resolving the error and restoring normal website functionality.
Original PR description
*= website_partnership, website_crm_partner_assign Currently, an error occurs when users try to access the `/partners` website page after upgrading database to saas-19.2. This issue occurs because…
*= website_partnership, website_crm_partner_assign Currently, an error occurs when users try to access the `/partners` website page after upgrading database to saas-19.2. This issue occurs because recent changes introduced in PR [1] added a new template as id `index_layout`. Inside this template, a `t-call` element was using a nested `t-set` element to define `additional_title`. We were referencing this `t-set` element in the XPath of the `index` template to override the value of `additional_title`. However, recent changes removed the `t-set` from the `t-call` and replaced it with a direct variable assignment inside the `t-call`. During the upgrade, the migration script automatically moves the `additional_title` attribute into `t-call` and removes the `t-set` from the `t-call` (see the script and related changes in [2]). As a result, the XPath expression that targets the `t-set` element fails because the referenced element no longer exists, which causes the error. This commit fixes the above issue by adapting the `t-call` element to match the recent changes introduced in [2]. Instead of relying on a nested `t-set` element, it now uses the variable directly as an attribute within the `t-call`, and updates the corresponding attribute child accordingly. [1]: https://github.com/odoo/odoo/commit/711c3baad58f3e0f1dc39cb90eb8176aba91e9dd [2]: https://github.com/odoo/odoo/pull/235469/changes#diff-29ae6f0bcf846a2fcaffc38fdd0d3b19ea328c133ff4dfe18cc9725715f34dd9 sentry-7400315548
This update corrects a formatting issue in the Danish UBL invoice export, specifically related to the Nemhandel system. Adding a required 'TaxCategory' node ensures compliance with UBL standards, preventing export errors and facilitating accurate invoice processing. This ensures invoices are correctly formatted for electronic delivery.
Original PR description
Add the TaxCategory node in AllowanceCharge node as it's a requirement for some UBL format. It has been spoted with Nemhandel, as it requires a single tax category in the AllowanceCharge. no-task Forward-Port-Of: odoo/odoo#270351
This update prevents errors in e-Waybill requests when the dispatch and delivery locations share the same pincode. The system now requires a distance to be specified in these cases, ensuring complete requests are sent to the GSP server and avoiding potential issues.
Original PR description
Prevent sending incomplete e-Waybill requests to the GSP server when the dispatch and delivery pincodes are identical. In such cases, the distance cannot be automatically determined and must be provided explicitly. This commit adds a validation to ensure a distance is set before generating the e-Waybill, avoiding incomplete requests and subsequent server-side errors. task-6234343 Forward-Port-Of: odoo/odoo#270495 Forward-Port-Of: odoo/odoo#268497
This update fixes an issue where self-orders created through kiosks or mobile ordering didn't show the correct table information on the payment screen. The fix ensures that table details are accurately displayed for all self-order transactions, improving the customer experience and order accuracy.
Original PR description
### **Issue** Self-orders created through the mobile QR menu or kiosk were not displaying table information in the Order Info section of the payment screen. ### **Root Cause** The Order Details…
### **Issue** Self-orders created through the mobile QR menu or kiosk were not displaying table information in the Order Info section of the payment screen. ### **Root Cause** The Order Details dialog relied on `order.getTable()` to retrieve table information. However, self-orders only store the table reference through `table_id`, which was not properly handled when rendering the dialog, resulting in missing table information. ### **Solution** This PR introduces the following changes: * Add a dedicated `getTableInfo()` helper in `pos_restaurant` to retrieve table information from the order. * Use `getTableInfo()` when building the Order Details dialog fields. * Allow self-order flows to provide table information through `table_id`, ensuring table details are displayed correctly. ### **Steps to Reproduce** 1. Enable the following options in POS Configuration: * QR Menu & Ordering * Service at Table * Online Payment 2. Open a self-order from the mobile QR menu 3. Select a table and complete the payment 4. Open the POS session 5. Open the paid self-order 6. Click the **Details** button on the right side ### **Video Reproduction** https://drive.google.com/file/d/138AoJCTF1HNlCGFgk9BRTb0UTai-uXX7/view?usp=sharing ### **Before** Table information was not displayed in the **Order Info** section for self-orders. ### **After** Table information is now correctly displayed for self-orders. opw-6179516 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where new tasks created through Timesheets Assistant Rules were incorrectly set as private. The fix ensures that tasks are always associated with a project, preventing this unwanted behavior and improving task management consistency. This change enhances user experience and data accuracy within the Timesheets module.
Original PR description
Steps to reproduce: - Install Timesheets and enable Timesheets Assistant. - Go to Timesheets -> Configuration -> Assistant Rules. - Open an existing rule or create a new one. - Select a Project and enter a new Task name. Issue 1: - Click Create. - The task is created as a private task, and the project is cleared. Issue 2: - Click Create and Edit. - Remove the project and save. - The task is saved as a private task. Cause: - When using Create, the `default_project_id` from the context is not applied, so the task is created as a private task. - When using Create and Edit, users can remove the prefilled project before saving, which also results in a private task. Fix: - Pass `default_project_id` and `form_view_ref='project.view_task_form_res_partner'` in the context. This prefills the project and makes it required when creating a task. task-6293306 Forward-Port-Of: odoo/enterprise#120862
This update resolves an issue where DIAN XML files were being rejected due to incorrect payment calculations. The fix combines payment amounts into a single tag, ensuring accurate data transmission to the DIAN and preventing errors related to negative payment amounts.
Original PR description
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the…
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the PoS - Order a product - Before paying, make the amount we are paying bigger than the amount due - We get an error response from the API, the error is saying that the total due does not match what we paid **Why the fix:** Currently, the xml is rejected because the sum of the **PaidAmount** in the **PrepaidPayment** tag is not equal to what we are trying to pay for. This is happening because to avoid the fact that we can not send a line with negative amount, we used the **abs()** function on the line amount to make it positive. The negative line comes from the fact that when we have a total due that is below the amount paid, we create a new payment line with a negative amount to balance it out. But as we can't send lines with negative amount, we needed to make it positive. This does not work, as the sum of the lines' amount will then be too much compared to what we are paying for, because instead of substracting it we will be adding it. To avoid this, we now group the amount in one single tag and send it this way. This ensures that the sent amount is correct and equals the amount due, and does not send a negative line. opw-6232575 Forward-Port-Of: odoo/enterprise#121075 Forward-Port-Of: odoo/enterprise#119255
This update resolves an issue where sign templates with auto-filled fields would incorrectly display placeholders instead of the actual values, or fail to generate documents. The fix ensures falsy auto-filled values are properly handled, preventing errors and guaranteeing accurate sign document generation.
Original PR description
Version: - 19.0 Steps to reproduce: - Create a sign template with a readonly sign item linked to an auto field. - Use a reference record where the linked field value is empty or False. - Send the…
Version: - 19.0 Steps to reproduce: - Create a sign template with a readonly sign item linked to an auto field. - Use a reference record where the linked field value is empty or False. - Send the document for signing. - Complete the signing flow. Issue: - Readonly sign items linked to auto-filled values could not properly handle falsy values. Empty values could trigger the error "Some required items are not filled" and completed sign requests displayed the sign item placeholder instead of the actual auto-filled value. - completed document generation could fail when rendering falsy values for textarea sign items. Cause: - Falsy auto-filled values were ignored during constant item population and replaced by the sign item placeholder. Additionally, readonly constant items were included in required field validation and completed sign requests continued to display placeholders when the stored value was empty. - document rendering assumed sign item values were always strings for textarea sign items but when auto field is empty it value can be False. Fix: - Preserve falsy values when populating readonly constant items, exclude constant items from signer validation, and hide placeholders for empty auto-filled constant items when displaying completed sign requests. - Normalize falsy values to prevent crashes and allow completed documents to be generated correctly. Forward-Port-Of: odoo/enterprise#121009
This update corrects a bug where custom styling of text inputs within Odoo wasn't working correctly. The previous version prevented users from applying their own styles to text inputs. This change ensures that styling options passed to text inputs now function as intended, providing greater flexibility in design.
Original PR description
BuilderTextInput's template hardcoded `inputClasses` to 'o-hb-input-text', dropping any `inputClasses` prop passed by callers. As a result, options trying to style their text input had no effect. Introduced in 0aba7f383c86dec00e9fc6d324a5bfdec7a19707. Concatenate caller-supplied `inputClasses` with the default `o-hb-input-text`. Forward-Port-Of: odoo/odoo#265156
This update corrects an issue where the link editor unexpectedly appeared when creating new tracked links. The fix ensures the editor only opens when a user actively wants to modify a link, preventing confusion and improving the user experience. This resolves a minor bug that could have caused frustration for users.
Original PR description
Steps to reproduce: - Go to the Link Tracker page - Generate a first tracked link - Click on the button to start editing the code - Click on "create another tracker" - Generate a second tracked link => When you access the screen to see/edit the tracked link url, the buttons "ok" and "cancel" are already present. Clicking on "ok" display a traceback. To fix this issue, this commit also cancels edition when clicking on "create another tracker". task-4531974 Forward-Port-Of: odoo/odoo#269886 Forward-Port-Of: odoo/odoo#268573
This update fixes an issue where the chatter in Odoo POS incorrectly displayed the employee who made changes to tracked orders. Now, the chatter accurately reflects the employee currently interacting with the order, ensuring accurate order tracking and communication. This improves order management and reduces potential confusion.
Original PR description
**Steps to reproduce:** - Enable "Track orders edits" in the settings - Enable "Log in with Employees" - Go to the Restaurant, log in with employee A - Go to a table, order 3 Sushis - Go back to the…
**Steps to reproduce:** - Enable "Track orders edits" in the settings - Enable "Log in with Employees" - Go to the Restaurant, log in with employee A - Go to a table, order 3 Sushis - Go back to the floor plan and change to employee B - Go back to the table and change the qty of 3 Sushis to 2 Sushis - Go to the order in the backend and check the chatter - It will indicate that employee A did the change, but it was employee B **Why the fix:** We always used the cashier set on the order to determine who should be put in the chatter, regardless of who is actually connected at that point. We now use the session's current employee to write who did the change in the chatter. We do not change the order's employee, because it will be done once the order has been paid. In the case where we are not logged in but pos_hr is installed, the employee_id might be the id of a res.user, and browsing it might return the wrong value. To avoid this, we check if the value exists as a hr.employee before assigning the name. The way we return the value has been changed because the linter wasn't happy about it. opw-6213504 Forward-Port-Of: odoo/odoo#270416 Forward-Port-Of: odoo/odoo#265582
This update corrects a bug where the system incorrectly forecasted expiring perishable products as unavailable, leading to unnecessary reordering. Now, the system accurately reflects stock levels and avoids triggering replenishment for perishable goods until they actually expire, resolving confusion for users.
Original PR description
Currently when the user receives a perishable product that expires in future, it is considered for reordering regardless if the user has maximum quantity or not. ## Steps to produce: - Install…
Currently when the user receives a perishable product that expires in future, it is considered for reordering regardless if the user has maximum quantity or not. ## Steps to produce: - Install Inventory - Go to settings > Enable 'Lots and Serial Numbers' and 'Expiration Dates' - Create a product 'Vegetable Oil' that is tracked by lots. - Enable Expiration date in the 'Inventory' Section and set Removal date to 2. - Create a receipt for 'Vegetable oil' with Demand 10 and mark it as todo - Details > Set 'Expiration Date' into the future > Set a Lot Number and Save - Validate the receipt - Open Product Form for Vegetable oil > Reordering Rules. - Create a new Reordering rule with Min 5 and Max 10 and save. ## Observed Behavior: The forecasted quantity is calculated as zero, resulting in a quantity to order of 10, even though no replenishment is actually required. The product already satisfies the maximum quantity defined on the reordering rule, and there is no existing demand, as there are no delivery orders or sales order reservations for the product. **Why this is an issue:** When the user navigates from the product form to the On Hand Quantity view to verify the stock situation, the forecasted quantity is shown as 10. This is inconsistent with the value displayed on the reordering rule, creating confusion and making it difficult to understand the actual inventory status. In addition, if the product is configured with a Buy route, running the `Procurement: Run Scheduler` action repeatedly generates new purchase orders for the perishable product. Even if the generated purchase orders are cancelled or completed, since newly purchased stock will also have an expiration date. As a result, the same incorrect forecast calculation occurs again, causing the scheduler to continuously create new purchase orders and leading to an endless replenishment cycle if they expire within horizon days. ## Root cause: When an orderpoint is created or updated, `_compute_qty_to_order` [1] is triggered. This method calls `_compute_qty_to_order_computed` [2] which accesses the forecasted quantity, causing its compute method to called. The forecast computation retrieves context from `_get_product_context` as seen in [3], where the lead horizon date (route lead time + horizon days configured in settings) is passed as `to_date` at [4]. It then reads the product's `virtual_available` quantity using the orderpoint context at [5]. This ultimately invokes `_compute_quantities`, which delegates the calculation of `virtual_available` to `_compute_quantities_dict`, as shown in [6]. As a result, `max_date` is set to the lead horizon date at [7] (for example, one year in the future). Since the product expires before that date, it is included in `expired_unreserved_quant_res`, causing `virtual_available` to be reduced to zero at [8]. Consequently, the forecasted quantity also becomes zero at [9]. Because the forecasted quantity falls below the orderpoint's minimum quantity, a replenishment is incorrectly triggered. **Why did this issue not occur in previous versions?** This behavior was introduced by [commit](https://github.com/odoo/odoo/commit/8ba2c1e38b636c567511139c5e19b7189430a182 ), which fixed the calculation of fresh(unexpired) quantity displayed in the stock availability widget on sales order lines. Which expects that `scheduled_date` (typically the committed delivery date or expected delivery date, including leadtime) is passed to `read_qties` at [10] , which stores it in the context using the `to_date` key. However, the same `to_date` key is also used by the orderpoint horizon-days logic. This overlap causes the expiration-aware quantity computation to use the horizon date instead of the intended `with_expiration` date , leading to incorrect forecast calculations and the unexpected replenishment behavior described above. [1]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/stock_orderpoint.py#L394-L396 [2]-https://github.com/odoo/odoo/blob/96b7eed9153eab60288d1624252df6f90ea9505e/addons/stock/models/stock_orderpoint.py#L417-L427 [3]- https://github.com/odoo/odoo/blob/96b7eed9153eab60288d1624252df6f90ea9505e/addons/stock/models/stock_orderpoint.py#L374-L381 [4]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/stock_orderpoint.py#L484-L491 [5]- https://github.com/odoo/odoo/blob/96b7eed9153eab60288d1624252df6f90ea9505e/addons/stock/models/stock_orderpoint.py#L386 [6]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/product.py#L152-L154 [7]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/product.py#L215-L218 [8]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/product.py#L260-L262 [9]- https://github.com/odoo/odoo/blob/9ae1df190cf5ee6a5775eddb32be7b13f5ed92c9/addons/stock/models/stock_orderpoint.py#L391 [10]- https://github.com/odoo/odoo/blob/afa2b6b7b47d6420146ceb6dad897405aa92c682/addons/sale_stock/models/sale_order_line.py#L129 ## Solution It does not make sense to trigger replenishment for perishable products solely because they are expected to expire before the horizon date. Even when the available quantity already satisfies the maximum quantity defined on the reordering rule, the current logic forecasts those products as unavailable in advance of their expiration. Instead, products should only be excluded from the forecast once they have actually expired, or when they must be removed according to the original expiration-handling logic. To achieve this, an additional context key can be introduced to distinguish calls originating from the forecast availability widget from SO line. When the computation is performed for the forecast widget, the existing `to_date` context key should continue to be used so that availability is evaluated at the requested future date. For all other flows, including orderpoint calculations, the system should rely on the `with_expiration` context key instead. This preserves the original behavior, where only already-expired quantities (or quantities that must be removed due to expiration rules) are excluded from availability calculations, preventing incorrect replenishment recommendations for perishable products. opw-6200644 Forward-Port-Of: odoo/odoo#268223
This update significantly reduces the memory usage and processing time when loading large General Ledger reports. By optimizing how display names are retrieved, the system now handles complex reports more efficiently, leading to a smoother user experience. This change addresses a performance bottleneck impacting report loading speed.
Original PR description
### Issue Loading a large General Ledger (e.g., during an "Unfold All" action) and retrieving display names for thousands of journal lines (`account.move.line`) causes excessive memory and…
### Issue Loading a large General Ledger (e.g., during an "Unfold All" action) and retrieving display names for thousands of journal lines (`account.move.line`) causes excessive memory and performance overhead. Profiling with `memray` showed that one of the main memory hotspots was located in `custom_label_builder`. **Previous behavior:** Accessing `record.display_name` in a loop without an explicit `fetch()` call triggered lazy computation of the field via `_compute_display_name()`. When the compute method accessed stored dependency fields (such as `name`, `ref`, `move_id`), each cache miss went through `_fetch_field()`, which greedily loaded **all fields sharing the same prefetch group** on the model, far beyond the dependencies of `display_name` alone. This caused the ORM cache to be filled with many unnecessary stored fields for every record in the prefetch set. --- ### Dataset Volume The performance metrics were captured using a dataset consisting of: * **455,694** Journal Items (`account.move.line`) * **19,947** Journal Entries (`account.move`) --- ### Solution Add a single `fetch(['display_name'])` call on the browsed recordset. By calling `fetch(['display_name'])` upfront, the ORM goes through `_determine_fields_to_fetch(['display_name'])`, which walks only the declared `field_depends` of `display_name` and fetches **only those specific stored fields**. nothing more. --- ### Impact & Results | Metric | Before Optimization | After Optimization | Change / Note | | :--- | :--- | :--- | :--- | | **Peak Memory** | ~856 MB | ~223 MB | ~74% reduction | | **Execution Time** | 2.48s | 2.13s | About the same time with multiple tries | OPW-6275158 Forward-Port-Of: odoo/enterprise#121020
This update fixes a visual issue in the spreadsheet dashboard where focused buttons were obscured by the surrounding container. The change ensures that buttons have their expected focus shadows, creating a cleaner and more professional user experience. This improves usability and overall appearance.
Original PR description
the searchbar container cropped the shadow of its button when they were focused. Task-6303342 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#270812
This update resolves an issue where invoices with reverse charge tax in Poland (fa3) were generating incorrect XML files for transmission to the KSEF. Specifically, the XML lacked the necessary information to accurately reflect the reverse charge amount and total sale value. This ensures proper tax reporting and compliance.
Original PR description
**STEP TO REPRODUCE** 1. Create an invoice with a tax with reverse charge (0% EU G for example). 2. Send the invoice to ksef. 3. Open the generated xml, and notice field P_18 is 2 while it should be 1 (because there is reverse charge). Also, there is not P13_10 indicated the total value of sale to which the reverse charge applies. opw-6041836 Forward-Port-Of: odoo/odoo#263764
This update fixes a visual issue where the field selection popover overlapped with the dropdown in the HTML editor. By adjusting the z-index, the dropdown now correctly appears in front of the popover, providing a smoother and more intuitive user experience when selecting fields. This ensures consistent functionality for creating and editing content.
Original PR description
a4efb745e9f4ba24dfa01f1e17e65f1a7cac90a5 merged the web_studio dynamic field and the mass_mailing dynamic field into a single field selector, included from the HTML editor. This introduces a new flow…
a4efb745e9f4ba24dfa01f1e17e65f1a7cac90a5 merged the web_studio dynamic field and the mass_mailing dynamic field into a single field selector, included from the HTML editor. This introduces a new flow where the user has to first "activate" the field selector popover ( /field ), which appears as an overlay item; then open the ModelFieldSelector dropdown to select a field on its model, which appears as another overlay item. As both overlay items overlap, and they have the same "z-index" property, the last sibling in the overlay container appears first. In mass_mailing, the ModelFieldSelector selector dropdown's overlay item is introduced as the first child of that container; this results in the dropdown appearing behind the item through which it was opened. Fix: Overlay items holding a Dynamic Field Popover have their z-index property reduced by 1, ensuring they appear behind their ModelFieldSelectors at all times. Steps to reproduce: - Create a new mailing - Add in any text node - Type in /field - Press Enter - Click the [-] to select a field task-5477951
This update fixes a potential issue causing unpredictable behavior in the website's dynamic content rendering. By adding 'protection' to the snippet's callback, the system now handles changes more reliably, preventing unexpected errors. This ensures a smoother and more consistent user experience on the website.
Original PR description
Commit dcb070244dbcef59cae1e3b1e87ce9030608ce0d changed the registration of callback for re-render of dynamic snippet on window resize. But did not ensure the callback is "protected", like it was implicitely done with `t-on-` in `dynamicContent`. This commit uses `protectSyncAfterAsync` to register the callback, so that is it protected when called again. This lack of "protection" is suspected to cause a non-deterministic failure in `test_shop_editor_no_alternative_products_visibility` where mutations of dom are observed at unexpected times. runbot-939193 Forward-Port-Of: odoo/odoo#271011
This update fixes an issue where delivery note costs (DDT) were incorrectly calculated for products tracked across multiple lots. The fix ensures that the total sale price of all lots is used in the cost calculation, resulting in accurate DDT pricing. This improves the reliability of financial reporting for multi-lot sales.
Original PR description
Steps to reproduce: 1. Install Italian localization and l10n_it_stock_ddt 2. Create a product tracked by lots with a price of 100 3. Create two lots for that product, each with 5 in stock 4. Create a sale order for a quantity of 8 5. Confirm the sale order and validate the delivery 6. Print the delivery note Issue: Only the first lot's sale price is used in the DDT cost calculation (price = 500 instead of 800) Why this happens: The QWeb template used `move.move_line_ids[0].sale_price`, which only reads the sale_price of the first move line. When a delivery is split across multiple lots, each lot produces its own move line, so only the first is considered in the price calculation. opw-6244076 Forward-Port-Of: odoo/odoo#270743 Forward-Port-Of: odoo/odoo#267757
This update prevents users from being added to member history when joining an already finished live chat through an invite link. This ensures that chat statistics are accurate and consistent with the latest Odoo version (19.3). It's a technical adjustment to improve data reliability.
Original PR description
Avoid adding users to member history when joining an already ended live chat via an invite link. This prevents skewed chat statistics and aligns behavior with 19.3. partial backported PR: [odoo/pull/224920/](https://github.com/odoo/odoo/pull/224920) task-6317650 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where manually added by-products on manufacturing orders caused errors during production closure. The fix ensures that serial numbers are correctly applied to by-products created outside of the standard BOM process, improving the reliability of the shopfloor operation.
Original PR description
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application.…
**Issue** Adding a serial-tracked by-product manually on a Manufacturing Order whose BOM does not define it, can lead to inconsistencies when assigning serial numbers in the shopfloor application. **Steps to reproduce** - Activate by-product in the settings - Create a product with an empty BOM (final product) - Create another product tracked by serial number (by-product) - Create and confirm a MO for the final product with 1 unit of the by-product - Go to Miscellaneaous -> operation Type -> shopfloor - Activate the option "Pre fill lot/serial numbers in shop floor" - Return to the MO and open the shopfloor view - Click on the '+' button next to the by-product and assign a serial number - Try to close the production -> A user error is raised stating that the by-product requires a serial number. **Cause** When the by-product is added manually on the MO, a stock move is created with an initial move line that does not contain any serial number. Later, when assigning a serial number from the shopfloor view: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L121-L122 a new move line containing the serial number is created: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L116-L119 However, the original empty move line is not removed (the issue): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/mrp_workorder/models/stock_move.py#L124-L125 Because `self.picking_type_prefill_shop_floor_lots` is True, but `self.byproduct_id` is an empty recordset since: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1304-L1311 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/mrp/models/mrp_production.py#L1279 Indeed, `byproduct_id` is only populated from BOM-defined by-products. As a result, while confirming the production, there is 2 sml and among them, the original one without SN, which triggers the error: https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L590 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L634-L635 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L658-L659 https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/addons/stock/models/stock_move_line.py#L661-L669 opw-6223158 Forward-Port-Of: odoo/enterprise#118792
This update streamlines the process for applying Early Payment Discounts (EPD) to refund transactions. Previously, a technical issue prevented correct tax repartitioning, now resolved by ensuring the system correctly identifies and maps invoice and refund lines for EPD calculations. This enhancement improves the accuracy and reliability of EPD processing on refunds.
Original PR description
This commit does not bring native support for EPD on credit notes, only makes custom support a little easier and cleaner. It is quite easy to support EPD (early payment discounts) on refunds by…
This commit does not bring native support for EPD on credit notes, only makes custom support a little easier and cleaner. It is quite easy to support EPD (early payment discounts) on refunds by extending - `_early_payment_discount_move_types` - `_is_eligible_for_early_payment_discount` However, this approach breaks when it reaches `inverse_tax_rep` in `_get_invoice_counterpart_amls_for_early_payment_discount_per_payment_term_line`, which assumes tax repartition lines with `document_type == 'invoice'` and raises when called on `tax_rep` lines of 'refund' type instead. This commit fixes that by selecting source and target repartition lines according to the `tax_rep`'s document type, which ensures: - the `.index()` no longer raises a `ValueError`, as `tax_rep` is now looked up in the matching set (`refund_` for refunds, `invoice_` otherwise) - `inverse_tax_rep` returns the corresponding line in the opposite set, preserving the original invoice->refund mapping while adding the refund->invoice one Since `inverse_tax_rep` is a closure, downstream modules cannot patch it without copying the whole ~170-line method. Making it symmetric here lets custom EPD-on-refund support work without that duplication. task-[6265601](https://www.odoo.com/odoo/all-tasks/6265601) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271102
This update resolves a bug that previously prevented the system from correctly calculating bill addresses when address fields were empty. Now, empty address fields are automatically set to blank strings, ensuring accurate billing information is processed. This improves the reliability of payment authorization transactions.
Original PR description
Fix bug introduced by commit https://github.com/odoo/odoo/pull/267592/changes/c4556637e8eeef07ce6e3cc3b3b4cf28fa10e468 that caused an error if an address field was not set, due to trying to cut a False field. Now, unset fields are set to empty strings. Forward-Port-Of: odoo/odoo#270295
This update corrects a visual issue where product images in the grid layout didn't appear in the expected left-to-right order. The change ensures that image navigation within the product image viewer now accurately reflects the visual arrangement of images, improving the user experience.
Original PR description
This commit ensures product images follow their visual order in the product image viewer when using the grid layout. Steps to reproduce: - Open a product page with multiple images (or add Extra Media…
This commit ensures product images follow their visual order in the product image viewer when using the grid layout. Steps to reproduce: - Open a product page with multiple images (or add Extra Media to the product) - Change layout mode to "Grid" and click save - Click any image to open the product image viewer - Navigate between images Images do not follow the visual left-to-right order. This regression was introduced by [commit], which replaced the row-based grid with a column-first layout. As a result, `querySelectorAll` returns images in DOM order, which no longer matches the visual order. To fix this, images are now reordered based on their visual placement in the grid so navigation matches the order seen by the user. Images are traversed in visual left-to-right order while also accounting for varying image heights and multi-column alignment. [commit]: https://github.com/odoo/odoo/commit/9a3628b9735550bf8ecc2252ea1b7338f68ab966 task-[4364143](https://www.odoo.com/odoo/project/974/tasks/4364143) Forward-Port-Of: odoo/odoo#270732 Forward-Port-Of: odoo/odoo#254077
This update fixes an issue where appointment invitations weren't always sent when appointments were in statuses other than 'booked' or 'request'. The change ensures that invitations are consistently sent for appointments, improving the user experience and preventing missed meeting notifications. This was originally identified and addressed in a related enterprise PR.
Original PR description
This PR adapts the code to fix the invitations at the appointments' update. See the enterprise PR to get more information about the issues. Enterprise PR: https://github.com/odoo/enterprise/pull/114304 Task-6139036 Forward-Port-Of: odoo/odoo#270925 Forward-Port-Of: odoo/odoo#260073
This update fixes issues with sending appointment invitations, ensuring they're only sent when an appointment is actually booked or requested. Previously, invitations were sent even when appointments were cancelled or updated, leading to unnecessary emails. This ensures a cleaner and more reliable invitation process for users.
Original PR description
This PR fix three issues related to the sending of the appointment invitations. Each one has its own commit: - Commit 1 sends invitations only if the event either "booked" or "request". Previously they were sent even if the appointment was cancelled. - Commit 2 prevents the sending of regular invitations and always sends appointment invitation to new attendees of existing booked appointments. - Commit 3 sent appointment invitations if the status of an existing event is set "request". It also add the status change in the log as it would have been if it was done at the creation. Community PR: https://github.com/odoo/odoo/pull/260073 Task-6139036 Forward-Port-Of: odoo/enterprise#121081 Forward-Port-Of: odoo/enterprise#114304
This update fixes an issue where the table of contents would obscure headings when the status bar was made sticky. The change adjusts how the table of contents scrolls to ensure headings remain visible, improving the user experience when navigating long documents.
Original PR description
Since [1] when the `o_form_statusbar` status bar was made `sticky` the table of content scrolls to a given heading without taking it into account. Because of this, when scrolling upwards the heading ends up behind the status bar. This commit fixes this by finding top-aligned sticky elements within the closest scrollable element impacted by the table of content. Steps to reproduce: - Go to a To do note - Define some headings - Have sufficient content so that reaching a heading requires scrolling - Define a table of content with `/toc` - Click on a heading => The heading ended up behind the status bar. [1]: https://github.com/odoo/odoo/commit/a3c63413825cf3492a10ade77a2c571c4eeb33a6 task-6302762 Forward-Port-Of: odoo/odoo#270043
This fix resolves an issue where invoices for returned dropshipped products incorrectly displayed both lot numbers instead of just the correct one. The update ensures that the invoice accurately reflects the returned product's serial/lot number, improving inventory accuracy and reporting. This was caused by a misinterpretation of return move lines during invoice generation.
Original PR description
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print on the invoice
-> The generated PDF displays "lot1 & lot2" instead of "lot1"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 2` since the invoice is on a quantity of 2 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic (as they should be): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80
- for the last one, `is_stock_return = False` while it should not, thus the quantity is 1 instead of 0. Furthermore, it does not pass by this code:
https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/sale_stock/models/account_move.py#L79 which would make the quantity for lot2 equalled to 0 (1-1) The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 1, lot2: 0}`
The report selects both lots since it starts with lot1 (qty of 1): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6236855
Forward-Port-Of: odoo/odoo#270599This update fixes two issues related to USPS shipping rates. First, it now displays the correct packaging dimension unit of measure, resolving confusion about inch vs. foot conversions. Second, it ensures USPS rates are calculated accurately based on the selected service type, not just domestic or international.
Original PR description
Issue ----- There are 2 issues with USPS rest: 1. USPS packagings do not have their size UOM displayed. This leads to confusion as users input in inches but the dimensions are treated as feet. 2.…
Issue ----- There are 2 issues with USPS rest: 1. USPS packagings do not have their size UOM displayed. This leads to confusion as users input in inches but the dimensions are treated as feet. 2. USPS returns the same rate regardless of the package type. Steps to reproduce ----- - Set USPS up - Open the Package Type form > go to its' Dimensions tab > Issue 1 - Set USPS up (domestic) - Select a `Domestic Rating Indicator` (eg LF - Flat Rate Box) - Create a SO with some product - Open the delivery widget and add a rate with USPS - Discard the changes - Go to the delivery method and change the rating (eg SP - Single Piece) - Go back to the SO - Open the delivery widget and add a rate with USPS > Issue 2, rate is the same as before Issue 1 ----- By default, there is no displayed UOM on the form because of https://github.com/odoo/odoo/blob/38c737c2a4cc29b48235a100cfa9d6152af73826/addons/stock_delivery/models/stock_package_type.py#L20-L33 We can change this behaviour for USPS specifically as done in Envia https://github.com/odoo/enterprise/blob/20cc61e69aa3f6a59de1e962b25ce11fa402bf22/delivery_envia/models/stock_package_type.py#L37-L46 Issue 2 ----- In `usps_rest_rate_shipment`, we request rates for every package of the delivery, which we receive as lists. We then iterate over the list to find the rate matching the `mail_class`. The problem is that this only filters over whether the delivery is domestic or international. We don't filter based on the actual service selected on the carrier (`usps_domestic_rating_indicator` for domestic and `usps_international_rating_indicator` for international). https://github.com/odoo/enterprise/blob/20cc61e69aa3f6a59de1e962b25ce11fa402bf22/delivery_usps_rest/models/delivery_usps.py#L224-L236 ----- Ticket: opw-6224918 Forward-Port-Of: odoo/enterprise#120789 Forward-Port-Of: odoo/enterprise#120594
This update resolves an issue where mass email campaigns were incorrectly using users' personal email servers, causing delays and errors. The changes ensure that personal servers are excluded from mass mailing selections and campaign execution, improving reliability and preventing campaigns from getting stuck.
Original PR description
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few…
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few problems: 1. Admins cannot duplicate a personal server. The copy keeps the same owner, and the rule that says one user can own only one server stops the save. 2. In *Email Marketing > Settings*, the "Dedicated Server" picker offers every server, even personal ones. If an admin picks a personal one, all campaigns get stuck. The cron job runs as Odoobot, the personal server rejects it, and the mailing stays in the queue. 3. When no dedicated server is set, the fallback selection can still land on a personal server (for example because its `from_filter` matches the sender). The cron sends through it and gets rejected. One commit per problem: 1. **mail**: duplicating a personal server now produces a copy with no owner. 2. **mass_mailing**: the picker in the settings hides personal servers. Setting an owner on a server that is already used for mass mailing now raises a clear error that names the campaign blocking the change. 3. **mass_mailing**: personal servers are skipped when the fallback selection runs, so only shared servers are considered. opw-6086077 Forward-Port-Of: odoo/odoo#270607 Forward-Port-Of: odoo/odoo#261537
This update fixes an issue where comment counts on course slides weren't accurately reflecting the number of active comments. The change adjusts how comments are tracked due to recent portal chatter updates, ensuring the displayed count matches the actual number of comments. This improves the user experience for course reviews.
Original PR description
Steps to reproduce: - Open a slide of a course in non fullscreen mode (website). - Go to the comments tab and add a comment in the chatter. - The comments count does not change in the tab. - The same thing happens when a comment is deleted. - Another way to see the incorrect counter is to add a note in the slide form view (backend). Before this change, `website_slides` used `website_message_ids` to calculate the comments. Since #138233 the old portal chatter has been replaced with the mail chatter and the way messages are displayed on the portal has changed. For example notes are no longer considered portal messages and also deleted messages should not be displayed or counted as such. This change ensures that comments calculations are based on a domain that considers those changes meaning that comments will be synced with the actual number of available comments. Forward-Port-Of: odoo/odoo#270800 Forward-Port-Of: odoo/odoo#260376
This update significantly speeds up appointment scheduling by optimizing how the system checks resource availability. The change eliminates a redundant process, resulting in faster slot availability checks, particularly when managing many resources like tables in a restaurant. This improves the user experience and system responsiveness.
Original PR description
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that…
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that resource. Also, linked resources information is added when computing the original resource remaining capacity. If many linked resources exist, this will be done several times and is not useful. This commit makes that loop disappear. We now check all resources at once in terms of availability, and linked resources that could be selected (in the appointment resources, in the slot resources (if any restricted resource)) at the same time. Then, the total capacity is the sum of the resource remaining capacity and the ones of available linked resources. Therefore, _slot_availability_is_resource_available is renamed to _slot_available_resources, as it now takes more than one resource and returns all resources among 'resources' that are valid on the slot, based on the availability_values, slot restrictions and booking lines. A noticeable difference is mainly seen when using many resources (and linked resources). For instance, a restaurant with a lot of small tables will have their slot availability check much shorter. BENCHMARK, LOCAL (time only, as number of requests does not change) Only appointment installed For a restaurant with - 10 tables of 2 - 5 tables of 2 linked, 2 times - 10 tables of 4 - 2 table of 2 - time then auto assign On loading /appointment/id: ~ 3.1s -> ~ 1.6s On selecting any number of people (1 to 10): [2s, 2.5s] -> [0.6s, 0.8s] Task-4144524 Forward-Port-Of: odoo/enterprise#121005 Forward-Port-Of: odoo/enterprise#107711
This update fixes a reporting issue where Preparation Time reports displayed incorrect hour buckets due to using the OdooBot's timezone instead of the user's. Now, reports accurately reflect preparation times based on the user's local timezone, ensuring consistent and reliable data for business analysis.
Original PR description
In POS, the Preparation Time report groups average preparation durations by hour. Those hour buckets were always computed with the timezone of the user who ran the module upgrade (OdooBot /…
In POS, the Preparation Time report groups average preparation durations by hour. Those hour buckets were always computed with the timezone of the user who ran the module upgrade (OdooBot / superuser), not the timezone of the user viewing the report. Changing the user, company, or browser timezone had no effect on the graph until the module was upgraded again. Steps to reproduce: ------------------- * Configure a Preparation Display and create POS orders with measured preparation times. * Open Point of Sale → Reporting → Preparation Time. * Note the hour bucket used for the orders. * Change your user timezone in Preferences and reload the report. > Observation: The hour buckets stay the same. Before the fix, they only changed after upgrading `pos_enterprise`, because the timezone was embedded in the SQL view created during `init()` as superuser. Why the fix: ------------ Replace the static PostgreSQL view with a dynamic `_table_query` so `order_hour` is computed with the current user's timezone on each report read. `init()` now only drops the legacy view instead of recreating it with a frozen timezone. opw-6220248 Forward-Port-Of: odoo/enterprise#118365
This update resolves a bug preventing Avatax exemption code synchronization. The issue stemmed from AvaTax returning '*' to indicate all countries, which was incorrectly interpreted as 'False' by the system. This fix ensures correct country ID handling, allowing successful synchronization and improved functionality.
Original PR description
Steps to reproduce: - Create a US company - Go to Accounting > Configuration > Settings - Activate `Avatax` > Set Credentials - Try to "Sync Parameters" Traceback: ```py File…
Steps to reproduce:
- Create a US company
- Go to Accounting > Configuration > Settings
- Activate `Avatax` > Set Credentials
- Try to "Sync Parameters"
Traceback:
```py
File "/home/odoo/src/enterprise/saas-19.2/account_avatax/models/res_company.py", line 113, in avatax_sync_company_params
'valid_country_ids': [(6, 0, get_countries(vals['validCountries']).ids)],
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/account_avatax/models/res_company.py", line 90, in get_countries
return self.env['res.country'].browse([country_cache[code] for code in code_list])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/models.py", line 5208, in browse
assert all(ids) or all(isinstance(x, NewId) or x for x in ids), "Invalid falsy real id"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Invalid falsy real id
```
The issue occurs because AvaTax return `*` in the `validCountries` field to indicate that an exemption code is valid for all countries. The synchronization logic stores this value in the country cache as `False` and later passes it to `res.country.browse()`. Since `browse()` does not accept a mix of valid IDs and falsy values, the operation crashes during the synchronization process.
This commit filter out falsy country IDs when resolving country codes to prevent crashes and allow exemption codes to be synchronized successfully.
opw-6298189
Forward-Port-Of: odoo/enterprise#120845This update prevents users from changing the status of checks when they don't have the necessary permissions. Previously, attempting to modify a check without selecting the main company would result in an error. Now, the status change button is disabled, ensuring data integrity and preventing unintended actions.
Original PR description
Before this commit: Only main company of tax unit have write access on check, so when main company is not selected and user tries to change status of check, access error is thrown. After this commit: Disable check status button if user don't have write access on check. task-5951364 Forward-Port-Of: odoo/odoo#271330
This update fixes a previous issue where self-order receipts lacked important company information like the logo, address, and contact details. Now, all relevant company and PoS settings are included on self-order receipts, improving customer experience and brand consistency.
Original PR description
Before this commit: ---------------- - Order receipts generated from self-orders were missing several company and PoS configuration details, such as the company logo, receipt address, phone number, email, and website. After this commit: ---------------- - Order receipts generated from self-orders now include all relevant company and PoS configuration details. Task-6271261
This update resolves an issue where the 'deliver' button wouldn't appear on sales orders without a product line. Previously, this prevented users from fulfilling orders when the stock module wasn't installed. The change ensures that all sales order lines, including those without products, correctly calculate delivery quantities.
Original PR description
In saas-19.2, note lines on SO's are no longer have a calculated
"manual" qty_delivered_method value. In the previous code, these would
prevent the deliver button showing on SO's (when stock was not
installed). These would also cause issues with the deliver action.
On Runbot (no apps installed):
1. Install Sales
2. Create SO with a product
3. Confirm SO
4. See deliver button dissapear
This change will correct a previous change so that sale order lines without a product will remain with a manual delivered method
opw-6280551
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update resolves a problem where users were incorrectly denied access to WhatsApp templates within the Event module. The fix prevents users from creating new WhatsApp templates, which was causing the 'User does not have access' error. This ensures proper WhatsApp communication functionality.
Original PR description
Issue: 1) User goes to Event.event Form -> communication tab -> add line 2) Select whatsapp -> type something -> create and edit -> create new template with any model event.registration -> save ( all the way including the event form) 3) reload page -> whatsapp event.mail displays "User does not have access to this record". Fix: add "'no_create_edit': True" to the associated field in the xml to block creation of new mail.templates opw-6037488 Forward-Port-Of: odoo/odoo#268641 Forward-Port-Of: odoo/odoo#259683
This update resolves an issue where loading demo data after installing the `l10n_in` module without pre-existing demo data would fail. The fix ensures that company IDs are correctly converted into a usable recordset, allowing users to successfully load demo data from the Settings menu. This improves the user experience and ensures consistent demo data setup.
Original PR description
## Description When loading demo data from **Settings** after installing `l10n_in` without demo data, the `_install_demo` method receives company IDs instead of a `res.company` recordset. As a…
## Description When loading demo data from **Settings** after installing `l10n_in` without demo data, the `_install_demo` method receives company IDs instead of a `res.company` recordset. As a result, the following line crashes: ```python companies.filtered(...) ``` with: ```text AttributeError: 'int' object has no attribute 'filtered' ``` This PR ensures that the received company IDs are converted into a `res.company` recordset before being processed, allowing demo data to be loaded successfully from the Settings menu. ## Steps to Reproduce 1. Install `l10n_in` **without demo data**. 2. Navigate to **Settings**. 3. Click **Load Demo Data**. ## Current Behavior Demo data installation fails with: ```text AttributeError: 'int' object has no attribute 'filtered' ``` ## Expected Behavior Demo data should be installed successfully without raising any exception. ## Solution Convert the received company IDs into a `res.company` recordset when the argument passed to `_install_demo` is not already a recordset. Forward-Port-Of: odoo/odoo#270523
This update resolves an issue where saving a job page description with only whitespace resulted in a validation error. The fix ensures that empty HTML fields are handled correctly during saving, preventing the 'Document is empty' error and allowing users to successfully update their job postings. This improves the user experience and prevents data loss.
Original PR description
Steps to reproduce: =================== 1. Edit a job page. 2. Delete every `s_rating` block. 3. Save. => Validation Error: Document is empty. Cause: ====== Deleting the last snippet inside an…
Steps to reproduce: =================== 1. Edit a job page. 2. Delete every `s_rating` block. 3. Save. => Validation Error: Document is empty. Cause: ====== Deleting the last snippet inside an editable HTML field (e.g. the last `s_rating` block in the `website_rating` field of a job page) leaves the field's editable container with only whitespace text nodes. On save, it writes that whitespace to the record and then calls `_copy_custom_snippet_translations`, which does `html.fromstring(lang_value)` on the whitespace and raises `lxml.etree.ParserError: Document is empty`, re-raised as `ValidationError`. The user sees a "Validation Error" dialog and can't finish saving. The previous fix for the analogous "Document is empty" symptom on product description editing (commit [1]) added a `cleanupEmptyStructures` `on_removed_handlers` that strips whitespace from `.oe_empty` containers after element removal. That selector covers `oe_structure.oe_empty` containers but not editable HTML field savables (`[data-oe-type="html"]`), which don't carry an `oe_empty` class when they originally had content. As a result, fields like `hr.job.website_rating` still hit the failing parse path. Solution: ========= Extend the cleanup selector to also include `[data-oe-type="html"]` so HTML-field editables are normalized to genuinely empty after the last inner snippet is removed. [1]: https://github.com/odoo/odoo/commit/53d5cc7eed635f64038bf0315f6863011879c529 opw-6244892 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270466 Forward-Port-Of: odoo/odoo#267397
This update corrects an issue where the FEC export file generated for French companies sometimes contained empty lines with zero balances. This prevented accurate financial reporting and data exchange with tax authorities. The fix ensures all accounts have a valid balance when exporting, improving data reliability.
Original PR description
Steps to reproduce: - Use a French company (l10n_fr_account installed) - Post prior-year entries so that an account/partner nets to zero at the start of the next fiscal year (e.g. a customer invoice fully paid the same year, or a misc entry debiting and crediting the same balance-sheet account), and keep another account/partner with a non-zero opening - Open the FEC export wizard, set Start Date to the first day of the next year - Generate the FEC file and look at the "Balance initiale" (OUVERTURE) lines Issue: One of the exported line in as empty one with `...|0,00|0,00|..`` opw-6083991 Forward-Port-Of: odoo/odoo#270658 Forward-Port-Of: odoo/odoo#268510
This update fixes a minor UX issue where the spreadsheet filter dropdown remained open even when the selected filter value hadn't changed. The fix ensures the dropdown automatically closes after the filter button is clicked, providing a more consistent and intuitive user experience. This improves usability and reduces potential confusion for users.
Original PR description
Current behavior before PR: - In b4d5d1f, added early return when filter value is unchanged. - However, the dropdown was not closed in this case, leaving it open after clicking the filter button, resulting in inconsistent and unexpected UX. Desired behavior after PR is merged: - Ensure the dropdown is closed even when the filter value remains unchanged, restoring consistent and expected behavior. Task: [6304213](https://www.odoo.com/odoo/project/2328/tasks/6304213) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270225
This update fixes an issue where the total invoice amount was not being displayed correctly in the order view. The change reintroduces a key field, ensuring accurate invoice amounts are shown to users. This improves clarity and accuracy in sales reporting.
Original PR description
This is a backport of 953e92b8bd79a39042c78ca7183ae73f90906c1e. `amount_to_invoice` is a technical field only used to trigger the credit limit warning on invoices/SOs and is not supposed to be shown in views. 6feba7b018e15738be145ce48be9761481e9e11a opw-6271335 Forward-Port-Of: odoo/odoo#270250
This update fixes an issue where clicking on an employee's avatar in the Discuss section displayed outdated information from archived records. The fix ensures that the correct, current employee details are shown, resolving a display inconsistency. This improves the user experience when accessing employee information.
Original PR description
*: hr_holidays,test_discuss_full **Steps to reproduce,** Create an employee linked to a user Archive the employee and remove the link to the user Create another employee for the same user Go to…
*: hr_holidays,test_discuss_full **Steps to reproduce,** Create an employee linked to a user Archive the employee and remove the link to the user Create another employee for the same user Go to Discuss > 'General' channel Open the member list and click on the user's avatar **Before this commit,** Clicking on the avatar opened a popover showing outdated information from the archived employee record instead of the new one. **Cause,** By default, the server sends employee data ordered by name. Since both records have the same name, the order is non-deterministic. The client then attempts to match the employee's company to the current user's company, falling back to the first record in the list if no match is found. **Fix,** Filter out archived records first (treating them as non-existent). Then, sort the remaining employee records to prioritize those that match the current user's active company. In case records share the same company, prioritize employees with a related user. Fall back to descending order of creation for identical results. **After this commit,** Clicking on the avatar shows the correct employee details in the popover. task-6175765 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270169 Forward-Port-Of: odoo/odoo#252170
This update resolves an issue related to how Odoo handles direct debit mandates for partner banks. The change adds a crucial check to ensure that direct debit setups are only processed against valid bank accounts, enhancing security and reliability. This improves the accuracy of payment processing for SEPA direct debit transactions.
Original PR description
Forward-Port-Of: odoo/enterprise#121236 Forward-Port-Of: odoo/enterprise#120901
Code cleanup and technical improvements
This update enhances the Odoo system by making a key component, `fragment_to_query_string`, more flexible and reliable. It now allows other Odoo modules to use this functionality, improving code organization and reducing potential issues. The changes also include important JUC compliance improvements through documentation and testing.
Original PR description
## [MOV] odoo,auth_oauth: fragment_to_query_string The aim of this commit is to allow module unrelated to auth_oauth to import fragment_to_query_string. task-id: 6071808 ## [REF] odoo: JUC compliant fragment_to_query_string The aim of this commit is to make `fragment_to_query_string` JUC compliant by: - documenting the behavior - clarifying the code - reducing possible side effect - testing the behavior - add a route to be able to test it manually task-id: 6071808 Forward-Port-Of: odoo/odoo#270834
This update ensures that a critical function used in social media integrations is correctly referenced within Odoo. This change supports ongoing development and maintenance of the social media features, ensuring they continue to function reliably. It’s a routine update to maintain the stability of the system.
Original PR description
The aim of this commit is to keep referencing fragment_to_query_string correctly as it is moved into `http.py`. task-id: 6071808 Forward-Port-Of: odoo/enterprise#121019
Documentation and clarification updates
This pull request formally records Adrien Didot's signature on the Odoo Individual Contributor License Agreement. It adds documentation confirming the CLA signing, ensuring compliance with Odoo's licensing terms. This update is a standard legal step for contributors.
Original PR description
Individual Contributor License Agreement signature. Adds `doc/cla/individual/adridot.md` per the CLA signing instructions. Related contribution: #270196 Forward-Port-Of: odoo/odoo#270411 Forward-Port-Of: odoo/odoo#270197