Daily updates from Odoo
Wednesday, May 13, 2026
257 changes
19 changes
Resolved issues and error corrections
This update resolves a technical error that prevented users from generating balance sheet comparisons correctly. The fix ensures that date types are consistently handled, allowing the 'Comparison' smart button to function as expected. This improves the reliability of balance sheet reporting.
Original PR description
Step to reproduce - Install the accountant module. - create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it - Navigate to Accounting > Report > Balance Sheet - Click the…
Step to reproduce
- Install the accountant module.
- create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it
- Navigate to Accounting > Report > Balance Sheet
- Click the `Comparison` smart button and set `Previous Period` to `2 periods`.
Observation:
- we face a traceback
``` File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5739, in _get_annotations
period_date_from = self._adjust_date_for_joined_comparison(options, period_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5695, in _adjust_date_for_joined_comparison
return min(period_date_from, comparison_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'datetime.date' and 'str'
```
Cause:
- `_get_period_dates` return string in case we have date which falls in
`custom_range_match`, when `get_report_information` is called, while
`period_date_from` is of type date
- hence there is mismatch between types
Fix:
- `_get_period_dates` is supposed to return date object always, hence fixed the
return type in case we have match for custom range
opw-6185629
Forward-Port-Of: odoo/enterprise#116350This update simplifies a confusing error message related to multiple GST registrations within an organization. The previous message led to wasted support time and incorrect reports. Now, users are prompted to verify their GST username matches their GST number, providing a clearer solution.
Original PR description
Users operating with multiple GST registrations (GST-wise branches/companies) could encounter a misleading error when the GST username belonged to a different GST number within the same organization. Previously, the system raised an error directly received from the server: [AUTH4041] Invalid Parameter state-cd in request header This message was confusing and led to unnecessary support tickets and false reports, as the issue was actually a mismatch between GST username and number. The error message has been updated to be more explicit and user-friendly: Please confirm that <gst_username> is associated with <gst_number>. Additionally, refactored duplicated logic by extracting the common code into a single helper function and reusing it across all occurrences. task-6041510 Forward-Port-Of: odoo/enterprise#111115
This update resolves an issue where rapid actions triggered duplicate entries being created in the database for account return checks. The fix prevents multiple simultaneous processes from attempting to create the same record, ensuring data integrity. This improves the stability and efficiency of the account reporting feature.
Original PR description
Issue -------------- When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to…
Issue
--------------
When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to the server. This created a race condition that resulted in duplicate `account.return.check` records being generated in the database.
steps to reproduce demonstrated in video: https://drive.google.com/file/d/1-A0ZHdYGdv-UL0dqClqK6Kos_iVXoZai/view?usp=sharing
When this happen the `runAllReturnChecks` method fires parallel RPC calls to [`refresh_checks`](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1974-L1992) on the server. In the case of instant multiple RPC calls, parallel threads are dispatched which causes the data preparation stage to run simultaneously.
Because both threads run in parallel, Thread 2 runs its [preparation and existing ](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1986-L1987 )check mechanism before Thread 1 has reached the actual `create()` function [trigger](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1998-L1999). Consequently, Thread 2's existence check fails to find the record (since Thread 1 hasn't committed it to the database yet), and it considers the record eligible for creation—even though the exact same record is already prepared for creation by Thread 1. This race condition leads to duplicate `account.return.check` records.
Logs to demonstrate the thread execution:
--------
```python
2026-04-16 08:30:51,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.000 0.002
2026-04-16 08:30:51,662 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.report/dispatch_report_action#account.report.dispatch_report_action HTTP/1.0" 200 - 17 0.006 0.012
2026-04-16 08:30:51,847 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 26 0.009 0.025
2026-04-16 08:30:52,099 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 95 0.029 0.064
2026-04-16 08:30:52,320 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.004
THREAD NAME: odoo.service.http.request.137360481711808 Thread ID: 137360481711808
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360481711808 -------------DATA PREPARING STAGE------------
Thread ID: 137360481711808
Thread ID: 137360481711808 RECORD EXISTING CHECK: None
2026-04-16 08:30:53,842 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:53] "GET /odoo/tax-report/tax-return?debug=1 HTTP/1.0" 200 - 29 0.020 0.021
2026-04-16 08:30:54,066 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/load_menus HTTP/1.0" 200 - 4 0.002 0.009
2026-04-16 08:30:54,351 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/manifest.webmanifest HTTP/1.0" 200 - 6 0.003 0.005
2026-04-16 08:30:54,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/translations?hash=bb5aa713d587cc7dd07b13d1d7efc2c525517e99&lang=en_US HTTP/1.0" 200 - 1 0.000 0.002
2026-04-16 08:30:54,586 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/bundle/web_tour.interactive?lang=en_US&debug=1 HTTP/1.0" 200 - 1 0.001 0.003
2026-04-16 08:30:54,640 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/action/load_breadcrumbs HTTP/1.0" 200 - 7 0.003 0.006
2026-04-16 08:30:54,710 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/ir.http/lazy_session_info#ir.http.lazy_session_info HTTP/1.0" 200 - 2 0.001 0.004
2026-04-16 08:30:54,753 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /bus/websocket_worker_bundle?v=19.0-2 HTTP/1.0" 304 - 3 0.004 0.006
2026-04-16 08:30:54,766 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/image?model=res.users&field=avatar_128&id=2 HTTP/1.0" 304 - 9 0.012 0.013
2026-04-16 08:30:54,777 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /mail/data HTTP/1.0" 200 - 34 0.034 0.020
2026-04-16 08:30:54,824 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 3 0.001 0.010
2026-04-16 08:30:54,934 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 88 0.029 0.051
2026-04-16 08:30:55,107 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.005
THREAD NAME: odoo.service.http.request.137360513177280 Thread ID: 137360513177280
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360513177280 -------------DATA PREPARING STAGE------------
Thread ID: 137360513177280
Thread ID: 137360513177280 RECORD EXISTING CHECK: None
2026-04-16 08:30:55,589 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.006
2026-04-16 08:30:56,702 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:56] "GET /web/service-worker.js HTTP/1.0" 200 - 1 0.000 0.003
2026-04-16 08:30:58,893 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:58] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.006 0.023
2026-04-16 08:31:05,296 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:05] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.002
Thread ID: 137360481711808 DATA to_create: 168
Thread ID: 137360481711808 done process create
2026-04-16 08:31:10,132 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:10] "POST /web/dataset/call_kw/account.return/refresh_checks#account.return.refresh_checks HTTP/1.0" 200 - 513 11.611 6.039
Thread ID: 137360513177280 DATA to_create: 168
Thread ID: 137360513177280 done process create
```
- OPW: 5917459
Forward-Port-Of: odoo/enterprise#114045This update fixes an issue where newly created stock batches were incorrectly named 'New' instead of following the standard 'BATCH/<TYPE>/000NN' naming convention. The change ensures that all new batches are correctly named, improving data consistency and reporting accuracy within the Delivery Orders feature. This resolves a bug impacting batch identification.
Original PR description
Steps to reproduce 1. Open the Barcode app > Operations > Delivery Orders. 2. Switch to the "Batches" tab. 3. Create a new one. Issue The created batch keeps the placeholder name "New" instead of…
Steps to reproduce
1. Open the Barcode app > Operations > Delivery Orders.
2. Switch to the "Batches" tab.
3. Create a new one.
Issue
The created batch keeps the placeholder name "New" instead of being
renamed to `BATCH/<TYPE>/000NN`.
The barcode kanban "New" button calls `open_new_batch_picking`, which
runs `Batch.create({})` while the action context carries
`default_picking_type_id` set by `stock.picking.type._get_action` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock/models/stock_picking.py#L432.
Since `vals` itself doesn't carry `picking_type_id`, the lookup in
`stock.picking.batch.create()` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock_picking_batch/models/stock_picking_batch.py#L181
returns an empty recordset, so the sequence-based rename branch is
skipped and the name stays at the field default `'New'`. The
subsequent `super().create` then applies the context default, so the
batch is correctly linked to a picking type but with the wrong name.
opw-6168320
Forward-Port-Of: odoo/enterprise#115809This update fixes a visual inconsistency in the appearance of website tabs when translating content. Specifically, it ensures that the translation state is correctly displayed for tab descriptions. This resolves a previously known issue, improving the overall user experience and consistency of the Odoo website.
Original PR description
Span elements which have a style that causes them to be displayed as "block" do not have the background color given by the translation span (this is a ["known" issue]) To show the translation state on those nodes, this commit uses the resource `force_background_translation_state_selectors` for the following: - `.o_nav_tabs_description`, the description of tabs in `s_tabs_images` Introduction of `force_background_translation_state_selectors`: cbb2eb2edfeecbc21a70c1a3cba81ad0a7ac9c75 ["known" issue]: https://github.com/odoo/odoo/commit/9addf9617830885532c27abb0ad5fa915e9f8f62 task-5892636 Forward-Port-Of: odoo/odoo#263620
This update fixes an issue where subsections remained visible on invoices even after the 'Hide Composition' option was selected. The underlying code was updated to ensure subtotals and unit prices are correctly hidden when this feature is enabled, aligning invoice presentation with 'Hide Prices'.
Original PR description
### Steps to reproduce: - Download 'Sales' app and create a product - Create an invoice with a section and a subsection - Set `Hide Composition` on the section - Add a product line under the subsection - Confirm and preview the invoice report > The subsection is still visible _Same issue occurs when activating 'Hide Prices'_ ### Cause of Issue: The `report_invoice.xml` file didn't include the right conditions to display the subtotals and unit prices in case of 'Hide Composition'/'Hide Prices'. Also, taxes were returned in `account_move_line` when they shouldn't be visible in case of 'Hide Prices'. ### Fix: Altered the conditions for sections and subsections, so that the information showing in 'Quotations' and 'Invoices' are consistent. opw-6069334 Forward-Port-Of: odoo/odoo#263944 Forward-Port-Of: odoo/odoo#258628
This update corrects a previous oversight by adding the 'l10n_pl_bank_verification' module to the weblate.json file. This ensures that the new bank verification functionality is correctly translated and available within the Odoo application for Polish users.
Original PR description
[FIX] Add l10n_pl_bank_verification to weblate.json In a previous PR, we added the new module 'l10n_pl_bank_verification' but didn't added it in weblate.json. This PR fix it See odoo/odoo#262518 Forward-Port-Of: odoo/odoo#263758
This update resolves a technical error that prevented the system from correctly identifying project documents when a project lacked a designated folder. The fix ensures the system handles projects with and without associated document folders smoothly, improving data accuracy and preventing potential errors during document retrieval.
Original PR description
The `_compute_documents()` method was expecting that the `documents_folder_id` field was always set.
However, the field is not required and can be empty.
This is not an issue if the compute is called on a single record, but when called on a recordset with :
- A project with related folder with at least one document
- A project with `documents_folder_id` empty The compute will fail because it calls `startswith()` with a parameter that is `False`.
```python
File "/home/odoo/src/enterprise/19.0/documents_project/models/project_project.py", line 50, in <lambda>
document_ids = documents.filtered(lambda doc: doc.parent_path.startswith(project.documents_folder_id.parent_path))
TypeError: startswith first arg must be str or a tuple of str, not bool
```
Solution:
Check for project-related documents only if the dedicated folder is set.
Forward-Port-Of: odoo/enterprise#117066This update refines how Odoo automatically matches bank statements to invoices and payments. Previously, it prioritized the closest date, which wasn't always accurate. Now, it only matches if there's one prior statement candidate, ensuring more reliable reconciliation and reducing potential errors in financial reporting.
Original PR description
Before this pr, we decided that when there was multiple candidates, we would take the one closer to the date of the statement line but it is not always what we want. We decided to change that so that it would match only if there is one candidate prior the date of the statement line. Exemple: Invoice 1 the 10/06 and invoice 2 the 20/06 → Payment the 05/06 → no matching (0 before) → Payment the 15/06 → match with invoice 1 (only 1 before) → Payment the 25/06 → no matching (More than 1 invoice open before) task-6143809 Forward-Port-Of: odoo/enterprise#115888 Forward-Port-Of: odoo/enterprise#115284
This update resolves an issue preventing accurate translation exports from the Web Studio interactive editor. A specific formatting error in the code templates was causing incorrect data extraction, leading to translation failures. The fix removes this problematic formatting to ensure correct export and translation of code.
Original PR description
It seems that the Babel Javascript tokenizer is not able to correctly parse a template string starting with a backslash and a newline. This caused it to extract pieces of code coming after it. The code excerpts would be exported in the POT file, but not applied to the JS code of course. The original message was not exported though, so it was not possible to translate it. This commit rewrites the template string to not use a backslash and a newline. This way the string is properly extracted and the code after it is not. Change was introduced by this commit[^1]. [^1]: https://github.com/odoo/enterprise/commit/56a2d9c4c2cc655af0469038d4c483581ac78864 Forward-Port-Of: odoo/enterprise#116927
This update fixes an issue where loyalty point transactions in POS orders were only recorded as a net difference, not the individual earned and spent amounts. The change ensures that the loyalty history accurately reflects the complete transaction, providing a more precise record of customer loyalty activity. This improves reporting and data accuracy for managing customer rewards.
Original PR description
When a loyalty card both earned and spent points in the same POS order, the history entry only reflected the net difference instead of the gross amounts. The root cause was that the JS payload sent only a single `points` field representing the net change. Fix by tracking `points_earned` and `points_spent` separately in `couponData` and sending them to the server. opw-6041420 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262314 Forward-Port-Of: odoo/odoo#256022
This update fixes a recurring issue where Odoo would repeatedly retry sending eTIMS transactions, leading to an error (924). The change improves reliability by intelligently handling network interruptions and ensuring that invoice numbers are not duplicated, preventing delays and data inconsistencies. This ensures smoother eTIMS processing for Kenyan customers.
Original PR description
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already…
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already exists). For POS orders, the old code decremented the sequence on any error (including timeout), so the next retry consumed the same invcNo. If eTIMS had already recorded the original send, the retry was rejected with 924. Fix by introducing a fetch-first strategy: on retry, if a pending invcNo is found in l10n_ke_order_json, call selectInvoiceDetails before sending. If eTIMS already has the invoice, recover the receipt data directly without resending. If eTIMS does not have it, resend with the same invcNo safely. On timeout errors, the sequence is no longer decremented so the invcNo is preserved in l10n_ke_order_json for the next idempotent retry. For customer invoices, the existing fetch-first logic only bailed out on TIM (timeout) errors, falling through on CON (connection) errors and retrying blindly. Additionally, if saveTrnsSalesOsdc returned 924, there was no recovery path and the invoice number would be cleared. Fix by also bailing on CON in the fetch block, and adding an explicit 924 handler that calls selectInvoiceDetails to recover the existing receipt instead of failing. opw-6105693 Forward-Port-Of: odoo/enterprise#115649
This update fixes a layout issue on the shop page for users who view the website in RTL (Right-to-Left) language settings. The previous layout was broken due to incorrect spacing, and this change ensures the shop grid displays correctly for all users. This improves the overall user experience for a wider range of customers.
Original PR description
Prior to this commit, the shop grid layout was broken in RTL due to misplaced left borders and padding. This commit adjusts those elements for RTL, fixing the layout. task-5933289 | Before | After | |--------|--------| | <img width="1406" height="869" alt="Screenshot 2026-05-04 at 10 37 56" src="https://github.com/user-attachments/assets/81f057cc-89d3-44f6-a723-9b439b88290d" /> | <img width="1392" height="877" alt="Screenshot 2026-05-04 at 10 36 53" src="https://github.com/user-attachments/assets/ded4eb4a-c82d-4114-ade6-5455f341a8f5" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262483
This update fixes a technical issue where linking restaurant tables could cause an infinite loop, potentially disrupting table management. The fix ensures correct table positioning calculations, particularly when tables are merged, preventing errors and maintaining data integrity. This improves the reliability of the restaurant table functionality.
Original PR description
Before this commit, it could happen that we try to link a restaurant table to another that was already its parent (for example by merging them while offline, we couldn't know that they were in a prent-child relation). This would lead to an infinite loop when trying to get the position of the table since it was computed based on the parent position so when a table is its own grand-parent, we get an active infinite loop. We solve the problem by going through the backend to merge tables. Task-id: 6183779 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262642 Forward-Port-Of: odoo/odoo#262509
This update fixes a bug that occurred when users tried to reschedule marketing activities, specifically within automated campaigns. The change prevents errors related to missing parent information, ensuring campaigns run smoothly and reliably. This improves the stability of our marketing automation features.
Original PR description
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the…
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save - An error will be thrown **Issue:** The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: `base_dt_str = trace.parent_id.schedule_date or trace.parent_id.mailing_trace_ids[0].write_date or trace.participant_id.create_date` **Fix:** Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-5362978 Forward-Port-Of: odoo/enterprise#107556
This update fixes a visual flicker in the timesheet timer field when saving data. By rounding the timer value on the server-side and validating record data before saving, the flicker is eliminated, ensuring a smoother and more reliable user experience. Additionally, the delete button visibility was adjusted to prevent a related flicker issue.
Original PR description
before: The timer value is rounded to the record, then the saving attempt is made. This makes the timer flicker to the rounded value for a split second if the saving operation failed (ex. missing data) after: The record is updated with the rounded value if the saving operation is valid. We check the record validity before saving or updating the record. --- task-6120567 Forward-Port-Of: odoo/enterprise#114502
This update adds sample accounting data specifically for the Italian localization (l10n_it). This allows our team to easily test and demonstrate the Italian version of Odoo, ensuring accurate reporting and compliance with Italian accounting standards. The data includes key elements like invoices, bank accounts, and EDI information.
Original PR description
Purpose: Load a pre-configured set of Italian accounting sample data to facilitate localization testing and demonstrations. Specifications: This commit introduces comprehensive sample data for the Italian localization, configuring the following: * Partners * Bank Accounts * Invoices & Bills * Dynamic Dates: All generated moves use a relative date format to ensure testing data remains relevant and doesn't expire on runbot. * EDI Data: Populates necessary e-invoicing fields (`l10n_it_codice_fiscale`, `l10n_it_pa_index`) for the created partners. task-6103257 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263881 Forward-Port-Of: odoo/odoo#262711
This update optimizes the PDF generation process for Odoo's SA (Saudi Arabia) edition, addressing a significant performance bottleneck. Previously, PDF creation was delaying checkout, but ZATCA now only requires XML and QR codes. This change dramatically speeds up the checkout process for SA users.
Original PR description
For SA companies, wkhtmltopdf PDF generation was accounting for ~47% of the sync_from_ui response time (~3.1s out of ~6.5s total), blocking the cashier at every order. The PDF is not needed during checkout: ZATCA requires only the signed XML and returns the QR code. The PDF can be generated on demand when the invoice is first viewed or downloaded. opw-6019994 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261417 Forward-Port-Of: odoo/odoo#253641
This update fixes an issue where file boxes, even after deleting their content, wouldn't be fully removed from the To-Do creation screen. The fix allows deleting non-editable file boxes when they are fully selected and their parent is editable, ensuring a cleaner user experience.
Original PR description
Problem: When adding a file box, selecting all content, and deleting, the file box is not removed. Cause: `o_file_box` is non-editable, so `canBeDeleted` returns `false` for this node, preventing its deletion. Solution: Allow deletion of non-editable nodes when they are fully selected and their parent is editable. Steps to reproduce: - Go to To-Do → Create New. - Upload a file. - Type some text next to the file. - Select all content (Ctrl + A or with the mouse). - Press Backspace/Delete multiple times. - Observe that the file box is not removed. task-6185206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263008
28 changes
Resolved issues and error corrections
This update resolves an issue where the DIAN (Colombia) information wasn't appearing on invoice PDFs in version 19.2. The fix simply reordered the layout of the PDF to ensure the required data was correctly rendered. This ensures accurate reporting for Colombian businesses using the Enterprise module.
Original PR description
**STEP TO REPRODUCE** 1. Setup DIAN. 2. Create an invoice. 3. Send it to dian. 4. Notice the cufe doesn't appear on the pdf. This fix moves the CUFE div before the informations div. Before the fix, it was placed at the top of the xml which appears to not render starting from 19.2. opw-6182706
This update resolves an issue where child partners in the Spanish localization were incorrectly flagged as companies. The fix ensures that child partners retain their correct status based on their individual commercial entity information, preventing misidentification as companies. This ensures accurate reporting and compliance within the Spanish tax system.
Original PR description
Step to reproduce: - install contacts and l10n_es and switch to ES company - create a partner, with valid vat ex. A12345674 - create a child partner from the form view Observation: - with debug mode,…
Step to reproduce: - install contacts and l10n_es and switch to ES company - create a partner, with valid vat ex. A12345674 - create a child partner from the form view Observation: - with debug mode, check that both records have `is_company` = True - child partner should not be considered as a company Cause: - After commit [1] `is_company` is a computed field, which can be overridden by other localization - in commit [2] for spain localizaton, `is_company` is true for all partner with valid CIF vat. - when we create a child partner, its value is synced with its parent at `_fields_sync` method with chain of methods finally leading to `vat` at `_synced_commercial_fields` - hence we propagate such commercial fields from parent to child - as now child also have same CIF vat, its is_comany = True [1] https://github.com/odoo/odoo/commit/f2965048f60fe6c815b3e50fa714c97a93dfb5d3 [2] https://github.com/odoo/odoo/commit/2d8013ccc858898fed52deac6eb11a8b5bb57351 Fix: - we now consider a partner as a company only when they own their commercial entity opw-6063786 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where users couldn't delete attachments from vendor bills after confirmation. The fix restricts a recent feature change to only 'comment' message types, addressing a technical limitation that prevented attachment deletion for notifications. This ensures users can properly manage attachments within the system.
Original PR description
Step to reproduce: - install purchase - create a RFQ, confirm it. a PO will be created - click on "upload bill" , upload a documnet, you will be sent for vendor bill - confirm the bill - try to…
Step to reproduce: - install purchase - create a RFQ, confirm it. a PO will be created - click on "upload bill" , upload a documnet, you will be sent for vendor bill - confirm the bill - try to delete the attachment from "paper-clip" icon Observation: - Error message: ```Only messages type comment can have their content updated ``` Cause: - commit [1] introduced a feature which adds "edited" tag in message body if attachment is removed, but that is only applicable for message with type == 'comment' https://github.com/odoo/odoo/blob/c3172d65db44c41f5619aef20532c3846494ea0e/addons/mail/models/mail_thread.py#L521-L531 - As this attachment is attached to record at time of creation, its type is "notification", and hence we are not able to delete this [1] https://github.com/odoo/odoo/commit/7c8971f2e2870fee19f55f971f3b8c8e553959c3 Fix: - we now limit the feature introduced by commit [1] only for message type "comment" opw-6055206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a problem where the tour worksheet wasn't consistently saving due to a timing issue. The fix adds a brief delay to ensure the worksheet is fully loaded before saving, preventing data loss. This improves the reliability of the tour process.
Original PR description
Currently, the test tour loads too quickly, so the worksheet is not saved properly. The issue happens because the worksheet is not yet visible on the portal view side. Therefore, i added an extra step to wait for the HTML field to load, giving enough time for the worksheet to be fully loaded. runbot error-242479 Forward-Port-Of: odoo/enterprise#116918
This update simplifies a confusing error message related to multiple GST registrations within an organization. Previously, users received a technical error that led to support requests. Now, the system clearly prompts users to verify the GST username matches the associated GST number, reducing support burden and improving user experience.
Original PR description
Users operating with multiple GST registrations (GST-wise branches/companies) could encounter a misleading error when the GST username belonged to a different GST number within the same organization. Previously, the system raised an error directly received from the server: [AUTH4041] Invalid Parameter state-cd in request header This message was confusing and led to unnecessary support tickets and false reports, as the issue was actually a mismatch between GST username and number. The error message has been updated to be more explicit and user-friendly: Please confirm that <gst_username> is associated with <gst_number>. Additionally, refactored duplicated logic by extracting the common code into a single helper function and reusing it across all occurrences. task-6041510 Forward-Port-Of: odoo/enterprise#111115
This update resolves an issue where rapid actions triggered duplicate account return checks, leading to unnecessary database entries. The fix ensures that only one check is created, improving system performance and data integrity. This was caused by a race condition in how the system processed multiple requests.
Original PR description
Issue -------------- When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to…
Issue
--------------
When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to the server. This created a race condition that resulted in duplicate `account.return.check` records being generated in the database.
steps to reproduce demonstrated in video: https://drive.google.com/file/d/1-A0ZHdYGdv-UL0dqClqK6Kos_iVXoZai/view?usp=sharing
When this happen the `runAllReturnChecks` method fires parallel RPC calls to [`refresh_checks`](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1974-L1992) on the server. In the case of instant multiple RPC calls, parallel threads are dispatched which causes the data preparation stage to run simultaneously.
Because both threads run in parallel, Thread 2 runs its [preparation and existing ](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1986-L1987 )check mechanism before Thread 1 has reached the actual `create()` function [trigger](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1998-L1999). Consequently, Thread 2's existence check fails to find the record (since Thread 1 hasn't committed it to the database yet), and it considers the record eligible for creation—even though the exact same record is already prepared for creation by Thread 1. This race condition leads to duplicate `account.return.check` records.
Logs to demonstrate the thread execution:
--------
```python
2026-04-16 08:30:51,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.000 0.002
2026-04-16 08:30:51,662 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.report/dispatch_report_action#account.report.dispatch_report_action HTTP/1.0" 200 - 17 0.006 0.012
2026-04-16 08:30:51,847 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 26 0.009 0.025
2026-04-16 08:30:52,099 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 95 0.029 0.064
2026-04-16 08:30:52,320 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.004
THREAD NAME: odoo.service.http.request.137360481711808 Thread ID: 137360481711808
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360481711808 -------------DATA PREPARING STAGE------------
Thread ID: 137360481711808
Thread ID: 137360481711808 RECORD EXISTING CHECK: None
2026-04-16 08:30:53,842 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:53] "GET /odoo/tax-report/tax-return?debug=1 HTTP/1.0" 200 - 29 0.020 0.021
2026-04-16 08:30:54,066 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/load_menus HTTP/1.0" 200 - 4 0.002 0.009
2026-04-16 08:30:54,351 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/manifest.webmanifest HTTP/1.0" 200 - 6 0.003 0.005
2026-04-16 08:30:54,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/translations?hash=bb5aa713d587cc7dd07b13d1d7efc2c525517e99&lang=en_US HTTP/1.0" 200 - 1 0.000 0.002
2026-04-16 08:30:54,586 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/bundle/web_tour.interactive?lang=en_US&debug=1 HTTP/1.0" 200 - 1 0.001 0.003
2026-04-16 08:30:54,640 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/action/load_breadcrumbs HTTP/1.0" 200 - 7 0.003 0.006
2026-04-16 08:30:54,710 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/ir.http/lazy_session_info#ir.http.lazy_session_info HTTP/1.0" 200 - 2 0.001 0.004
2026-04-16 08:30:54,753 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /bus/websocket_worker_bundle?v=19.0-2 HTTP/1.0" 304 - 3 0.004 0.006
2026-04-16 08:30:54,766 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/image?model=res.users&field=avatar_128&id=2 HTTP/1.0" 304 - 9 0.012 0.013
2026-04-16 08:30:54,777 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /mail/data HTTP/1.0" 200 - 34 0.034 0.020
2026-04-16 08:30:54,824 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 3 0.001 0.010
2026-04-16 08:30:54,934 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 88 0.029 0.051
2026-04-16 08:30:55,107 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.005
THREAD NAME: odoo.service.http.request.137360513177280 Thread ID: 137360513177280
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360513177280 -------------DATA PREPARING STAGE------------
Thread ID: 137360513177280
Thread ID: 137360513177280 RECORD EXISTING CHECK: None
2026-04-16 08:30:55,589 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.006
2026-04-16 08:30:56,702 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:56] "GET /web/service-worker.js HTTP/1.0" 200 - 1 0.000 0.003
2026-04-16 08:30:58,893 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:58] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.006 0.023
2026-04-16 08:31:05,296 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:05] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.002
Thread ID: 137360481711808 DATA to_create: 168
Thread ID: 137360481711808 done process create
2026-04-16 08:31:10,132 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:10] "POST /web/dataset/call_kw/account.return/refresh_checks#account.return.refresh_checks HTTP/1.0" 200 - 513 11.611 6.039
Thread ID: 137360513177280 DATA to_create: 168
Thread ID: 137360513177280 done process create
```
- OPW: 5917459
Forward-Port-Of: odoo/enterprise#114045This update enhances the logging of technical errors related to Saudi VAT (ZATCA) compliance within the odoo system. Previously, these errors were hidden from users to maintain a clean interface, but this made troubleshooting difficult. Now, server logs will record these errors with a specific prefix, allowing our team to quickly identify and resolve issues.
Original PR description
Log suppressed technical validation failures in server logs with a stable ZATCA_ERROR prefix while keeping user-facing errors unchanged. task-6110313 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261536
This update fixes an issue where newly created stock batches were initially named 'New' instead of following the standard 'BATCH/<TYPE>/000NN' naming convention. The fix ensures that all new batches are correctly named, improving data consistency and reporting accuracy within the Delivery Orders feature. This resolves a minor operational issue.
Original PR description
Steps to reproduce 1. Open the Barcode app > Operations > Delivery Orders. 2. Switch to the "Batches" tab. 3. Create a new one. Issue The created batch keeps the placeholder name "New" instead of…
Steps to reproduce
1. Open the Barcode app > Operations > Delivery Orders.
2. Switch to the "Batches" tab.
3. Create a new one.
Issue
The created batch keeps the placeholder name "New" instead of being
renamed to `BATCH/<TYPE>/000NN`.
The barcode kanban "New" button calls `open_new_batch_picking`, which
runs `Batch.create({})` while the action context carries
`default_picking_type_id` set by `stock.picking.type._get_action` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock/models/stock_picking.py#L432.
Since `vals` itself doesn't carry `picking_type_id`, the lookup in
`stock.picking.batch.create()` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock_picking_batch/models/stock_picking_batch.py#L181
returns an empty recordset, so the sequence-based rename branch is
skipped and the name stays at the field default `'New'`. The
subsequent `super().create` then applies the context default, so the
batch is correctly linked to a picking type but with the wrong name.
opw-6168320
Forward-Port-Of: odoo/enterprise#115809This update fixes a visual inconsistency in the website builder's tab design. Specifically, it ensures that translation states are correctly displayed on tab descriptions, resolving a previously identified issue. The change improves the overall user experience and consistency of the website.
Original PR description
Span elements which have a style that causes them to be displayed as "block" do not have the background color given by the translation span (this is a ["known" issue]) To show the translation state on those nodes, this commit uses the resource `force_background_translation_state_selectors` for the following: - `.o_nav_tabs_description`, the description of tabs in `s_tabs_images` Introduction of `force_background_translation_state_selectors`: cbb2eb2edfeecbc21a70c1a3cba81ad0a7ac9c75 ["known" issue]: https://github.com/odoo/odoo/commit/9addf9617830885532c27abb0ad5fa915e9f8f62 task-5892636 Forward-Port-Of: odoo/odoo#263620
This update resolves an issue where invoice subsections remained visible even after the 'Hide Composition' feature was enabled. The fix adjusted the underlying invoice report settings to ensure consistent display across 'Invoices' and 'Quotations', preventing unwanted subtotals and tax information. This improves invoice clarity and accuracy for users.
Original PR description
### Steps to reproduce: - Download 'Sales' app and create a product - Create an invoice with a section and a subsection - Set `Hide Composition` on the section - Add a product line under the subsection - Confirm and preview the invoice report > The subsection is still visible _Same issue occurs when activating 'Hide Prices'_ ### Cause of Issue: The `report_invoice.xml` file didn't include the right conditions to display the subtotals and unit prices in case of 'Hide Composition'/'Hide Prices'. Also, taxes were returned in `account_move_line` when they shouldn't be visible in case of 'Hide Prices'. ### Fix: Altered the conditions for sections and subsections, so that the information showing in 'Quotations' and 'Invoices' are consistent. opw-6069334 Forward-Port-Of: odoo/odoo#263944 Forward-Port-Of: odoo/odoo#258628
This update fixes a display issue where the number of ECOs listed on a Bill of Materials (BoM) was incorrect. The fix ensures that only ECOs directly associated with the current BoM version are counted, resolving a misleading display. This improves the accuracy of BoM information for users.
Original PR description
Steps to Reproduce (Fresh Database): -------------------------------------- 1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules 2. Create a product > New -- Name: "Test Product" > Save 3.…
Steps to Reproduce (Fresh Database):
--------------------------------------
1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules
2. Create a product > New -- Name: "Test Product" > Save
3. Create BoM v1
- Go to Manufacturing > Products > Bills of Materials > New --Product: Test Product
- Add component: any
4. Create and apply ECO 1 on BoM v1
- Go to PLM > ECOs > New-- Product: Test Product | Apply on: Bill of Materials
- BoM: Test Product (v1) > Confirm > Apply Changes
- This creates BoM v2 (previous_bom_id = BoM v1)
5. Create and apply ECO 2 on BoM v2
- Same as step 4 but select BoM v2
- This creates BoM v3 (previous_bom_id = BoM v2)
6. Create a separate unrelated BoM for the same product
- Go to Manufacturing > Bills of Materials > New
- Product: Test Product | Component: "Component B" > Save
7. Create ECO 3 on the separate BoM
- Go to PLM > ECOs > New - Product: Test Product | Apply on: Bill of Materials
- BoM: select the separate BoM from step 6 > Confirm
Observed Bug:
-------------
- Open BoM v3 > ECO(s) stat button shows count = 2
- Click the button > opens 3 records (ECO 3 incorrectly included)
Explain:-
----------
The ECO stat button on the BoM form was showing a mismatched count vs
the actual records opened when clicking it. This happened because
[button_mrp_eco](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L56) was using all keys from [_get_previous_boms](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L67)() as the
domain, which includes BoMs from unrelated lineages of the same product
template, while [_compute_eco_data](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L20) only counts ECOs belonging to the
current BoM's version lineage.
Fixed by filtering the domain to only include BoM IDs whose lineage set
contains the current BoM ID, making the opened records consistent with
the displayed count.
Before Fix
<img width="1901" height="875" alt="image" src="https://github.com/user-attachments/assets/3208aed5-ebd3-47a3-a457-a7d61b7743cb" />
```
In [24]: labo = self.env['mrp.bom'].browse(710)
In [25]: previous_boms_mapping = labo._get_previous_boms()
In [26]: Test = ['&', ('bom_id', 'in', list(previous_boms_mapping.keys())), ('type', '=', 'bom')]
In [27]: Test
Out[27]:
['&',
('bom_id',
'in',
[710,
1991,
2049,
1913,
1840,
1823,
1676,
1759,
1794,
1651,
1604,
1544,
1537,
1527,
1506,
1460,
1265,
1259,
1196,
1221,
1223,
1060,
1029,
960,
858,
850,
791,
739,
723,
698]),
('type', '=', 'bom')]
```
With My Fix
<img width="1824" height="947" alt="image" src="https://github.com/user-attachments/assets/0d68fdbc-7e42-4ce4-a326-2fb030ba1d06" />
```
In [15]: labo = self.env['mrp.bom'].browse(710)
In [16]: previous_boms_mapping = labo._get_previous_boms()
In [17]: previous_boms_mapping
Out[17]:
{710: {710},
1991: set(),
2049: set(),
1913: set(),
1840: set(),
1823: set(),
1676: set(),
1759: set(),
1794: set(),
1651: set(),
1604: set(),
1544: set(),
1537: set(),
1527: set(),
1506: set(),
1460: set(),
1265: set(),
1259: set(),
1196: set(),
1221: set(),
1223: set(),
1060: set(),
1029: set(),
960: set(),
858: set(),
850: set(),
791: set(),
739: set(),
723: set(),
698: {710}}
In [18]: relevant_bom_ids = [
...: bom_id
...: for bom_id, current_bom_set in previous_boms_mapping.items()
...: if labo.id in current_bom_set
...: ]
In [19]: relevant_bom_ids
Out[19]: [710, 698]
```
Task-6065020
Forward-Port-Of: odoo/enterprise#114039This update corrects a previous oversight by adding the 'l10n_pl_bank_verification' module to the Weblate translation file. This ensures that all user-facing text within the Odoo system is accurately translated for Polish bank verification processes, improving localization and user experience.
Original PR description
[FIX] Add l10n_pl_bank_verification to weblate.json In a previous PR, we added the new module 'l10n_pl_bank_verification' but didn't added it in weblate.json. This PR fix it See odoo/odoo#262518 Forward-Port-Of: odoo/odoo#263758
This update resolves a bug that prevented the system from correctly identifying project documents when the designated folder was empty. The fix ensures the system functions reliably regardless of whether a folder is associated with a project, improving document retrieval accuracy.
Original PR description
The `_compute_documents()` method was expecting that the `documents_folder_id` field was always set.
However, the field is not required and can be empty.
This is not an issue if the compute is called on a single record, but when called on a recordset with :
- A project with related folder with at least one document
- A project with `documents_folder_id` empty The compute will fail because it calls `startswith()` with a parameter that is `False`.
```python
File "/home/odoo/src/enterprise/19.0/documents_project/models/project_project.py", line 50, in <lambda>
document_ids = documents.filtered(lambda doc: doc.parent_path.startswith(project.documents_folder_id.parent_path))
TypeError: startswith first arg must be str or a tuple of str, not bool
```
Solution:
Check for project-related documents only if the dedicated folder is set.
Forward-Port-Of: odoo/enterprise#117066This update refines how Odoo automatically matches bank statements to invoices and payments. Previously, it prioritized the closest date, which wasn't always accurate. Now, it only matches if there's one prior statement candidate, ensuring more reliable reconciliation and reducing potential errors in financial reporting.
Original PR description
Before this pr, we decided that when there was multiple candidates, we would take the one closer to the date of the statement line but it is not always what we want. We decided to change that so that it would match only if there is one candidate prior the date of the statement line. Exemple: Invoice 1 the 10/06 and invoice 2 the 20/06 → Payment the 05/06 → no matching (0 before) → Payment the 15/06 → match with invoice 1 (only 1 before) → Payment the 25/06 → no matching (More than 1 invoice open before) task-6143809 Forward-Port-Of: odoo/enterprise#115888 Forward-Port-Of: odoo/enterprise#115284
This update fixes a previous issue where employee export reports were unavailable. It reintroduces the ability to generate these reports by updating the user interface and ensuring compatibility across installed modules. This ensures users can continue to generate necessary reports.
Original PR description
During the work entry apocalypse, the gantt view that was used to do the exports for Partena, Acerta etc was removed. With it, we lost the ability to trigger those reports, which we want to…
During the work entry apocalypse, the gantt view that was used to do the exports for Partena, Acerta etc was removed. With it, we lost the ability to trigger those reports, which we want to reintroduce here. To do so we create a dropdown element in the cog menu registry, which starts out empty but is populated with the various reports based on which modules are isntalled, by inheriting and adding the relative dropdown items. At the same time, currently the cogmenu of the employee when hr_presence is installed is being overridden to use HrPresenceCogMenu which adds a Dropdown of its own that includes actions related to employee presence. Therefore, we need to refactor this dropdown becuase depending on the module installation order the HrPresenceCogMenu might override the addition of the ExportCogMenu and overriding the CogMenu is not the correct way to add elements to it in general. I have been able to move the logic of the PresenceCogMenu to the registry but the actions don't have the correct context and give errors because the records are not passed. Also there are some problems with the ActionMenu (the one that shows up if you select employees from the lsit view. Task: 5985900
This update reintroduces the ability to export HR reports that were previously unavailable. The changes address an issue where export functionality was removed and now utilize a more robust method for adding export options based on installed modules. This ensures consistent reporting across different HR modules.
Original PR description
During the work entry apocalypse, the gantt view that was used to do the exports for Partena, Acerta etc was removed. With it, we lost the ability to trigger those reports, which we want to…
During the work entry apocalypse, the gantt view that was used to do the exports for Partena, Acerta etc was removed. With it, we lost the ability to trigger those reports, which we want to reintroduce here. To do so we create a dropdown element in the cog menu registry, which starts out empty but is populated with the various reports based on which modules are isntalled, by inheriting and adding the relative dropdown items. At the same time, currently the cogmenu of the employee when hr_presence is installed is being overridden to use HrPresenceCogMenu which adds a Dropdown of its own that includes actions related to employee presence. Therefore, we need to refactor this dropdown becuase depending on the module installation order the HrPresenceCogMenu might override the addition of the ExportCogMenu and overriding the CogMenu is not the correct way to add elements to it in general. I have been able to move the logic of the PresenceCogMenu to the registry but the actions don't have the correct context and give errors because the records are not passed. Also there are some problems with the ActionMenu (the one that shows up if you select employees from the lsit view. Task: 5985900
This update corrects a display issue in the survey time limit field, previously showing 'h' by default. The change ensures the time limit is consistently shown in minutes, aligning with how survey durations are defined, improving the user experience.
Original PR description
In the `time_limit` field, `h` was displayed by default next to the limit because as recently here https://github.com/odoo/odoo/commit/4751bbed988d8ee5233d70c4852ecbd5a03b228a we introduced the unit option for the `float_time` widget and by default that unit will fallback to hour so that's why `h` was displayed there. This PR addresses the issue and passed the minute as a unit as we were using the minutes for the survey time limit. Task-6132365
This update fixes an issue where scanning a packaging barcode (like '6' for a 6-pack) intermittently added quantities to the wrong line in the stock picking process. The fix ensures the barcode scan correctly identifies and updates the intended packaging unit, resolving quantity discrepancies.
Original PR description
Issue ----- When there are 2 lines for a single product and different packaging uoms, scanning a packaging barcode alternates between lines. Steps to reproduce ----- - Enable packagings - Create a…
Issue ----- When there are 2 lines for a single product and different packaging uoms, scanning a packaging barcode alternates between lines. Steps to reproduce ----- - Enable packagings - Create a product AAA - barcode 1 - Create a packaging 6-Pack - 6 units - barcode for AAA set to 6 - Create a PO - one line for 30 units of AAA - one line for 5 6-Pack of AAA - Confirm PO and open picking in barcode - Scan "6" multiple times > Quantity increases on both lines, alternating for each scan Cause ----- Both lines can be found as matching lines when doing https://github.com/odoo/enterprise/blob/d279632db25713dd639a51385cad197dfdbd2bdc/stock_barcode/static/src/models/barcode_model.js#L1426 The reason it alternates between the lines is because we set the currently selected line first in the array - and since both lines match, the `foundLine` returned ends up being the non-selected line. https://github.com/odoo/enterprise/blob/d279632db25713dd639a51385cad197dfdbd2bdc/stock_barcode/static/src/models/barcode_model.js#L1823-L1832 We can avoid this y refining the `break` condition of the loop to also match the packaging uom. ----- Ticket: opw-6034572 Forward-Port-Of: odoo/enterprise#112578
This update fixes an issue where the Table of Contents in the website's navigation bar wasn't displaying the correct translated text after styling headings. The fix ensures that translated headings are consistently shown in the navbar, regardless of inline styling, improving the user experience across multiple languages.
Original PR description
Steps to reproduce: =================== 1. Enable a second language on the website 2. Add a Table of Content snippet to a page 3. Apply bold (or any inline style) to one of the headings, save 4.…
Steps to reproduce: =================== 1. Enable a second language on the website 2. Add a Table of Content snippet to a page 3. Apply bold (or any inline style) to one of the headings, save 4. Switch to the second language in translation mode 5. Translate the styled heading and save => The TOC navbar entry keeps showing the source text on reload. => Expected: navbar shows the translated heading text, unstyled. Cause: ====== When a TOC heading carries inline markup, the server emits the heading and the navbar entry as two independent translation terms with different `data-oe-translation-source-sha` values, even though their textContent matches. A translation written under the heading's sha therefore never reaches the navbar's slot. `handleToC` was meant to bridge that by aliasing the navbar span's sha to the heading's during translation-mode setup, but two issues prevented it from working in saas-18.4+: - The TOC navbar lives under `.o_not_editable`, so its translation spans were excluded from `findOEditable` and `handleToC` never ran on them. The class `o_translation_without_style` was never added, and the sha was never aliased. Solution: ========= - `prepareTranslation` iterates TOC navbar translation spans explicitly, so `handleToC` reaches them despite `findOEditable` skipping `.o_not_editable`. - `handleToC` always tags the navbar span with `o_translation_without_style` when a matching heading exists. - An `after_replication_handlers` hook flags every replicated unstyled-translation target as `.o_dirty`, so the replicated translation is included in the save. opw-5950228 Forward-Port-Of: odoo/odoo#263547 Forward-Port-Of: odoo/odoo#260378
This update resolves an issue preventing accurate translation exports from the Web Studio interactive editor. A specific code formatting problem (using backslashes and newlines) was causing incorrect code extraction. The fix removes this problematic formatting, ensuring translations can now be properly exported and applied.
Original PR description
It seems that the Babel Javascript tokenizer is not able to correctly parse a template string starting with a backslash and a newline. This caused it to extract pieces of code coming after it. The code excerpts would be exported in the POT file, but not applied to the JS code of course. The original message was not exported though, so it was not possible to translate it. This commit rewrites the template string to not use a backslash and a newline. This way the string is properly extracted and the code after it is not. Change was introduced by this commit[^1]. [^1]: https://github.com/odoo/enterprise/commit/56a2d9c4c2cc655af0469038d4c483581ac78864 Forward-Port-Of: odoo/enterprise#116927
This update fixes a recurring issue where Odoo would retry eTIMS transactions, leading to errors (specifically 924) because it was using the same invoice number repeatedly. The fix ensures Odoo intelligently recovers existing invoice data when possible, improving the reliability of eTIMS processing for Kenyan VAT invoices. This prevents delays and ensures accurate data transmission.
Original PR description
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already…
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already exists). For POS orders, the old code decremented the sequence on any error (including timeout), so the next retry consumed the same invcNo. If eTIMS had already recorded the original send, the retry was rejected with 924. Fix by introducing a fetch-first strategy: on retry, if a pending invcNo is found in l10n_ke_order_json, call selectInvoiceDetails before sending. If eTIMS already has the invoice, recover the receipt data directly without resending. If eTIMS does not have it, resend with the same invcNo safely. On timeout errors, the sequence is no longer decremented so the invcNo is preserved in l10n_ke_order_json for the next idempotent retry. For customer invoices, the existing fetch-first logic only bailed out on TIM (timeout) errors, falling through on CON (connection) errors and retrying blindly. Additionally, if saveTrnsSalesOsdc returned 924, there was no recovery path and the invoice number would be cleared. Fix by also bailing on CON in the fetch block, and adding an explicit 924 handler that calls selectInvoiceDetails to recover the existing receipt instead of failing. opw-6105693 Forward-Port-Of: odoo/enterprise#115649
This update fixes a layout issue on the shop grid that was appearing incorrectly when Odoo is set to display content in Right-to-Left (RTL) languages. The changes adjust the layout elements to ensure a proper display for users in RTL environments, improving the overall user experience. This ensures all customers can easily browse and purchase products regardless of their language settings.
Original PR description
Prior to this commit, the shop grid layout was broken in RTL due to misplaced left borders and padding. This commit adjusts those elements for RTL, fixing the layout. task-5933289 | Before | After | |--------|--------| | <img width="1406" height="869" alt="Screenshot 2026-05-04 at 10 37 56" src="https://github.com/user-attachments/assets/81f057cc-89d3-44f6-a723-9b439b88290d" /> | <img width="1392" height="877" alt="Screenshot 2026-05-04 at 10 36 53" src="https://github.com/user-attachments/assets/ded4eb4a-c82d-4114-ade6-5455f341a8f5" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262483
This update fixes a technical problem that could cause the restaurant table management system to freeze due to an infinite loop when merging tables. The fix ensures that table relationships are correctly handled, preventing this error and improving system stability. This change focuses on internal system improvements.
Original PR description
Before this commit, it could happen that we try to link a restaurant table to another that was already its parent (for example by merging them while offline, we couldn't know that they were in a prent-child relation). This would lead to an infinite loop when trying to get the position of the table since it was computed based on the parent position so when a table is its own grand-parent, we get an active infinite loop. We solve the problem by going through the backend to merge tables. Task-id: 6183779 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262642 Forward-Port-Of: odoo/odoo#262509
This update fixes a bug that occurred when users tried to reschedule marketing activities, specifically within automated campaigns. The change prevents errors related to missing parent information, ensuring campaign scheduling works reliably. It also avoids potential user confusion by limiting modification options for test campaigns.
Original PR description
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the…
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save - An error will be thrown **Issue:** The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: `base_dt_str = trace.parent_id.schedule_date or trace.parent_id.mailing_trace_ids[0].write_date or trace.participant_id.create_date` **Fix:** Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-5362978 Forward-Port-Of: odoo/enterprise#107556
This update fixes a potential problem where multiple sign automation actions could silently override roles. The change adds a check within the automation process to ensure no conflicting roles are used, preventing incorrect permissions and maintaining data integrity. A new test has been implemented to verify this fix.
Original PR description
Before this commit, creating multiple server actions for the Sign app in a single transaction (e.g., when saving an Automation Rule with multiple nested actions) bypassed the `_check_sign_template_conflicts` constraint. Because the constraint only queried the database for existing links, it failed to detect conflicts within the in-memory batch, allowing the save to succeed and causing silent role overrides. This commit introduces an intra-batch check to the constraint. By tracking requested roles in memory during the loop, the constraint now correctly raises a ValidationError if multiple actions in the same transaction attempt to automate the exact same template roles. A test has been added to ensure batch creations are properly validated. Task: 6128909 Forward-Port-Of: odoo/enterprise#115062
This update fixes an issue where PDF Manager action names appeared awkwardly due to a styling class. The change removes this class, resulting in cleaner and more professional-looking action names within the PDF Manager interface. This improves the user experience and overall appearance.
Original PR description
Previously, pdf_manager actions used class "text-uppercase". Action names looked awkward. In this commit, we remove the class and properly display action names. task-6159317 Forward-Port-Of: odoo/enterprise#117000 Forward-Port-Of: odoo/enterprise#116382
This update fixes an issue where file boxes, even after deleting their content, wouldn't be fully removed from the To-Do creation interface. The fix allows deletion of non-editable file boxes when they are fully selected and their parent is editable, improving the user experience and ensuring content is accurately removed.
Original PR description
Problem: When adding a file box, selecting all content, and deleting, the file box is not removed. Cause: `o_file_box` is non-editable, so `canBeDeleted` returns `false` for this node, preventing its deletion. Solution: Allow deletion of non-editable nodes when they are fully selected and their parent is editable. Steps to reproduce: - Go to To-Do → Create New. - Upload a file. - Type some text next to the file. - Select all content (Ctrl + A or with the mouse). - Press Backspace/Delete multiple times. - Observe that the file box is not removed. task-6185206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263008
A recent test was failing due to inconsistencies in how account reports were loaded during automated testing. This update ensures the test accurately reflects the system's behavior by generating the necessary account reports within the test itself. This resolves a runbot error and maintains consistent test results.
Original PR description
Previously, embedded account reports always loaded the global account report. A fix introduced in version 19.0 changed this behavior so that the system now loads the most appropriate audit report,…
Previously, embedded account reports always loaded the global account report. A fix introduced in version 19.0 changed this behavior so that the system now loads the most appropriate audit report, specifically, the account report corresponding to the audit report's company (see: odoo/enterprise#101377). In version 19.1, a test was added to validate account report options. However, this test assumed that embedded account reports would always load the global account report (i.e., `account_reports.balance_sheet`). When tests run on runbot, demo data is not loaded. In that context, no report variants exist in the database, so the system falls back to the global account report, causing the test to pass. In environments where demo data is loaded, a report variant does exist, and the system correctly selects it instead of the global report. As a result, the test assertions are no longer valid and fail, leading to runbot errors. To address the issue, we will generate the account reports within the `setup` method of the test. This ensures that the assertions remain consistent, regardless of whether demo data is present. runbot-error-id~242235 Forward-Port-Of: odoo/enterprise#112486
18 changes
Resolved issues and error corrections
This update resolves a problem where the tour worksheet wasn't being saved correctly due to a timing issue. The fix adds a brief delay to ensure the worksheet is fully loaded before saving, preventing random failures. This ensures tour worksheets are reliably saved for users.
Original PR description
Currently, the test tour loads too quickly, so the worksheet is not saved properly. The issue happens because the worksheet is not yet visible on the portal view side. Therefore, i added an extra step to wait for the HTML field to load, giving enough time for the worksheet to be fully loaded. runbot error-242479 Forward-Port-Of: odoo/enterprise#116918
This update clarifies a confusing error message related to multiple GST registrations, making it easier for users to resolve issues. The original error was misleading, leading to unnecessary support requests. The new message directly prompts users to verify the connection between their GST username and number, streamlining the troubleshooting process.
Original PR description
Users operating with multiple GST registrations (GST-wise branches/companies) could encounter a misleading error when the GST username belonged to a different GST number within the same organization. Previously, the system raised an error directly received from the server: [AUTH4041] Invalid Parameter state-cd in request header This message was confusing and led to unnecessary support tickets and false reports, as the issue was actually a mismatch between GST username and number. The error message has been updated to be more explicit and user-friendly: Please confirm that <gst_username> is associated with <gst_number>. Additionally, refactored duplicated logic by extracting the common code into a single helper function and reusing it across all occurrences. task-6041510 Forward-Port-Of: odoo/enterprise#111115
This update resolves an issue where rapid actions triggered duplicate account return check records being created in the database. The fix prevents multiple simultaneous processes from attempting to create the same record, ensuring data integrity and preventing unnecessary database load. This improves system performance and stability.
Original PR description
Issue -------------- When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to…
Issue
--------------
When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to the server. This created a race condition that resulted in duplicate `account.return.check` records being generated in the database.
steps to reproduce demonstrated in video: https://drive.google.com/file/d/1-A0ZHdYGdv-UL0dqClqK6Kos_iVXoZai/view?usp=sharing
When this happen the `runAllReturnChecks` method fires parallel RPC calls to [`refresh_checks`](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1974-L1992) on the server. In the case of instant multiple RPC calls, parallel threads are dispatched which causes the data preparation stage to run simultaneously.
Because both threads run in parallel, Thread 2 runs its [preparation and existing ](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1986-L1987 )check mechanism before Thread 1 has reached the actual `create()` function [trigger](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1998-L1999). Consequently, Thread 2's existence check fails to find the record (since Thread 1 hasn't committed it to the database yet), and it considers the record eligible for creation—even though the exact same record is already prepared for creation by Thread 1. This race condition leads to duplicate `account.return.check` records.
Logs to demonstrate the thread execution:
--------
```python
2026-04-16 08:30:51,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.000 0.002
2026-04-16 08:30:51,662 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.report/dispatch_report_action#account.report.dispatch_report_action HTTP/1.0" 200 - 17 0.006 0.012
2026-04-16 08:30:51,847 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 26 0.009 0.025
2026-04-16 08:30:52,099 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 95 0.029 0.064
2026-04-16 08:30:52,320 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.004
THREAD NAME: odoo.service.http.request.137360481711808 Thread ID: 137360481711808
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360481711808 -------------DATA PREPARING STAGE------------
Thread ID: 137360481711808
Thread ID: 137360481711808 RECORD EXISTING CHECK: None
2026-04-16 08:30:53,842 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:53] "GET /odoo/tax-report/tax-return?debug=1 HTTP/1.0" 200 - 29 0.020 0.021
2026-04-16 08:30:54,066 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/load_menus HTTP/1.0" 200 - 4 0.002 0.009
2026-04-16 08:30:54,351 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/manifest.webmanifest HTTP/1.0" 200 - 6 0.003 0.005
2026-04-16 08:30:54,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/translations?hash=bb5aa713d587cc7dd07b13d1d7efc2c525517e99&lang=en_US HTTP/1.0" 200 - 1 0.000 0.002
2026-04-16 08:30:54,586 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/bundle/web_tour.interactive?lang=en_US&debug=1 HTTP/1.0" 200 - 1 0.001 0.003
2026-04-16 08:30:54,640 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/action/load_breadcrumbs HTTP/1.0" 200 - 7 0.003 0.006
2026-04-16 08:30:54,710 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/ir.http/lazy_session_info#ir.http.lazy_session_info HTTP/1.0" 200 - 2 0.001 0.004
2026-04-16 08:30:54,753 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /bus/websocket_worker_bundle?v=19.0-2 HTTP/1.0" 304 - 3 0.004 0.006
2026-04-16 08:30:54,766 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/image?model=res.users&field=avatar_128&id=2 HTTP/1.0" 304 - 9 0.012 0.013
2026-04-16 08:30:54,777 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /mail/data HTTP/1.0" 200 - 34 0.034 0.020
2026-04-16 08:30:54,824 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 3 0.001 0.010
2026-04-16 08:30:54,934 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 88 0.029 0.051
2026-04-16 08:30:55,107 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.005
THREAD NAME: odoo.service.http.request.137360513177280 Thread ID: 137360513177280
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360513177280 -------------DATA PREPARING STAGE------------
Thread ID: 137360513177280
Thread ID: 137360513177280 RECORD EXISTING CHECK: None
2026-04-16 08:30:55,589 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.006
2026-04-16 08:30:56,702 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:56] "GET /web/service-worker.js HTTP/1.0" 200 - 1 0.000 0.003
2026-04-16 08:30:58,893 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:58] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.006 0.023
2026-04-16 08:31:05,296 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:05] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.002
Thread ID: 137360481711808 DATA to_create: 168
Thread ID: 137360481711808 done process create
2026-04-16 08:31:10,132 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:10] "POST /web/dataset/call_kw/account.return/refresh_checks#account.return.refresh_checks HTTP/1.0" 200 - 513 11.611 6.039
Thread ID: 137360513177280 DATA to_create: 168
Thread ID: 137360513177280 done process create
```
- OPW: 5917459
Forward-Port-Of: odoo/enterprise#114045This update enhances the logging of technical errors related to Saudi VAT (ZATCA) compliance within the Odoo system. Previously, these errors were hidden from users to maintain a clean interface, but this made troubleshooting difficult. Now, server logs will record these errors with a specific prefix, allowing our team to quickly identify and resolve issues.
Original PR description
Log suppressed technical validation failures in server logs with a stable ZATCA_ERROR prefix while keeping user-facing errors unchanged. task-6110313 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261536
This fix resolves an issue where generating closing entries in the Inventory Valuation view incorrectly calculated values when multiple companies were selected. The update ensures that the generated account move lines accurately reflect the inventory valuation based on the selected main company, preventing incorrect balances.
Original PR description
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are…
**Problem:** In view Inventory valuation, generate entry doesn't work when multiple companies are selected. In the view only the main company matters. That means that even if multiple companies are selected, only the stock variation lines related to the main company selected are displayed (which is expected). But if you then click on 'generate entry' the account move lines created will have wrong values (not matching the values appearing in the view) **Steps to reproduce:** - create 2 new companies (to have clean accounting) - create a warehouse for both companies - for both comp, in settings for the 'fiscal localization' set Package : Generic Chart of account, if not already set (to have account journals). From company 1 : - create a storable prod with avco perpetual category - confirm PO for 2 @ 10, receive - bill only 1 @ 10 From company 2: - make sure the category is also perpetual average from this other company - confirm PO for 2 @ 50, receive, don't bill Notice how from the 'Inventory Valuation' view, rightfully, only the main company matters (no matter what other comp are selected): - If main comp is comp 1 there is stock variation lines for amount of 10 (which is expected because we have 20 in stock and only 10 in stock valuation account) - If main comp is comp 2 there is stock variation lines for amount of 100 (which is expected because we have 100 in stock and only 0 in stock valuation account) With comp 1 and 2 selected and comp 1 as main company: - click on 'Generate Entry' **Current behavior:** - both line have a balance of 110 **Expected behavior:** - they should have a balance of 10 as we saw on the 'inventory valuation' view **Cause of the issue:** To generate the data from the 'inventory valuation' view, inside _get_report_data() we call stock_value() and stock_accounting_value() to compare values from inventory and value from accounting. https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L36-L37 stock_value() sums total_value() of each product in the valued accounts https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L90-L94 Whereas stock_acounting_value(), sums the balance of each account move line of each valuation account https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L112-L114 All of this is related to the main company because we call _get_report_data() with context 'allowed_company_ids' set to only the main company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/report/stock_valuation_report.py#L13 But when we click on generate entry, _get_stock_valuation_account_vals() is called with no context modification to 'allowed_company_ids' so when we call stock_value(), https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L238-L239 total_value will be based on both company https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L92 Note that stock_accounting_value() is still rightfully based only on main company because we use self.id in the domain https://github.com/odoo/odoo/blob/dd84309df7fd39e9e97ed02d135d25b211085135/addons/stock_account/models/res_company.py#L105-L108 opw-6168699 Forward-Port-Of: odoo/odoo#262776
This update fixes an issue where newly created stock batches were incorrectly named 'New' instead of following the standard 'BATCH/<TYPE>/000NN' naming convention. The change ensures that all new batches are assigned the correct, predictable naming scheme, improving batch identification and reporting. This resolves a minor inconsistency in the system.
Original PR description
Steps to reproduce 1. Open the Barcode app > Operations > Delivery Orders. 2. Switch to the "Batches" tab. 3. Create a new one. Issue The created batch keeps the placeholder name "New" instead of…
Steps to reproduce
1. Open the Barcode app > Operations > Delivery Orders.
2. Switch to the "Batches" tab.
3. Create a new one.
Issue
The created batch keeps the placeholder name "New" instead of being
renamed to `BATCH/<TYPE>/000NN`.
The barcode kanban "New" button calls `open_new_batch_picking`, which
runs `Batch.create({})` while the action context carries
`default_picking_type_id` set by `stock.picking.type._get_action` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock/models/stock_picking.py#L432.
Since `vals` itself doesn't carry `picking_type_id`, the lookup in
`stock.picking.batch.create()` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock_picking_batch/models/stock_picking_batch.py#L181
returns an empty recordset, so the sequence-based rename branch is
skipped and the name stays at the field default `'New'`. The
subsequent `super().create` then applies the context default, so the
batch is correctly linked to a picking type but with the wrong name.
opw-6168320
Forward-Port-Of: odoo/enterprise#115809This update fixes a visual issue where the background color of translation spans wasn't consistently displayed on website tabs. The change utilizes a new resource to ensure that all tab descriptions accurately reflect the translation state, improving the overall user experience. This resolves a previously known issue.
Original PR description
Span elements which have a style that causes them to be displayed as "block" do not have the background color given by the translation span (this is a ["known" issue]) To show the translation state on those nodes, this commit uses the resource `force_background_translation_state_selectors` for the following: - `.o_nav_tabs_description`, the description of tabs in `s_tabs_images` Introduction of `force_background_translation_state_selectors`: cbb2eb2edfeecbc21a70c1a3cba81ad0a7ac9c75 ["known" issue]: https://github.com/odoo/odoo/commit/9addf9617830885532c27abb0ad5fa915e9f8f62 task-5892636 Forward-Port-Of: odoo/odoo#263620
This update fixes a display issue where the number of ECOs listed on a Bill of Materials (BoM) was incorrect. The fix ensures that the count accurately reflects the ECOs directly associated with the current BoM version, resolving a visual discrepancy and improving data accuracy. This impacts users reviewing BoM details and associated ECOs.
Original PR description
Steps to Reproduce (Fresh Database): -------------------------------------- 1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules 2. Create a product > New -- Name: "Test Product" > Save 3.…
Steps to Reproduce (Fresh Database):
--------------------------------------
1. Install `Manufacturing` (mrp) and `PLM` (mrp_plm) modules
2. Create a product > New -- Name: "Test Product" > Save
3. Create BoM v1
- Go to Manufacturing > Products > Bills of Materials > New --Product: Test Product
- Add component: any
4. Create and apply ECO 1 on BoM v1
- Go to PLM > ECOs > New-- Product: Test Product | Apply on: Bill of Materials
- BoM: Test Product (v1) > Confirm > Apply Changes
- This creates BoM v2 (previous_bom_id = BoM v1)
5. Create and apply ECO 2 on BoM v2
- Same as step 4 but select BoM v2
- This creates BoM v3 (previous_bom_id = BoM v2)
6. Create a separate unrelated BoM for the same product
- Go to Manufacturing > Bills of Materials > New
- Product: Test Product | Component: "Component B" > Save
7. Create ECO 3 on the separate BoM
- Go to PLM > ECOs > New - Product: Test Product | Apply on: Bill of Materials
- BoM: select the separate BoM from step 6 > Confirm
Observed Bug:
-------------
- Open BoM v3 > ECO(s) stat button shows count = 2
- Click the button > opens 3 records (ECO 3 incorrectly included)
Explain:-
----------
The ECO stat button on the BoM form was showing a mismatched count vs
the actual records opened when clicking it. This happened because
[button_mrp_eco](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L56) was using all keys from [_get_previous_boms](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L67)() as the
domain, which includes BoMs from unrelated lineages of the same product
template, while [_compute_eco_data](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/mrp_plm/models/mrp_bom.py#L20) only counts ECOs belonging to the
current BoM's version lineage.
Fixed by filtering the domain to only include BoM IDs whose lineage set
contains the current BoM ID, making the opened records consistent with
the displayed count.
Before Fix
<img width="1901" height="875" alt="image" src="https://github.com/user-attachments/assets/3208aed5-ebd3-47a3-a457-a7d61b7743cb" />
```
In [24]: labo = self.env['mrp.bom'].browse(710)
In [25]: previous_boms_mapping = labo._get_previous_boms()
In [26]: Test = ['&', ('bom_id', 'in', list(previous_boms_mapping.keys())), ('type', '=', 'bom')]
In [27]: Test
Out[27]:
['&',
('bom_id',
'in',
[710,
1991,
2049,
1913,
1840,
1823,
1676,
1759,
1794,
1651,
1604,
1544,
1537,
1527,
1506,
1460,
1265,
1259,
1196,
1221,
1223,
1060,
1029,
960,
858,
850,
791,
739,
723,
698]),
('type', '=', 'bom')]
```
With My Fix
<img width="1824" height="947" alt="image" src="https://github.com/user-attachments/assets/0d68fdbc-7e42-4ce4-a326-2fb030ba1d06" />
```
In [15]: labo = self.env['mrp.bom'].browse(710)
In [16]: previous_boms_mapping = labo._get_previous_boms()
In [17]: previous_boms_mapping
Out[17]:
{710: {710},
1991: set(),
2049: set(),
1913: set(),
1840: set(),
1823: set(),
1676: set(),
1759: set(),
1794: set(),
1651: set(),
1604: set(),
1544: set(),
1537: set(),
1527: set(),
1506: set(),
1460: set(),
1265: set(),
1259: set(),
1196: set(),
1221: set(),
1223: set(),
1060: set(),
1029: set(),
960: set(),
858: set(),
850: set(),
791: set(),
739: set(),
723: set(),
698: {710}}
In [18]: relevant_bom_ids = [
...: bom_id
...: for bom_id, current_bom_set in previous_boms_mapping.items()
...: if labo.id in current_bom_set
...: ]
In [19]: relevant_bom_ids
Out[19]: [710, 698]
```
Task-6065020
Forward-Port-Of: odoo/enterprise#114039This update corrects a previous oversight by adding the 'l10n_pl_bank_verification' module to the project's translation files (weblate.json). This ensures that all user-facing text related to this new bank verification feature is correctly translated and available in Polish. This resolves a potential issue with inconsistent translations.
Original PR description
[FIX] Add l10n_pl_bank_verification to weblate.json In a previous PR, we added the new module 'l10n_pl_bank_verification' but didn't added it in weblate.json. This PR fix it See odoo/odoo#262518 Forward-Port-Of: odoo/odoo#263758
This update resolves a technical bug that prevented the system from correctly identifying project documents when a project lacked a designated folder. The fix ensures the system functions smoothly regardless of whether a project has a linked folder, improving document retrieval reliability. This change impacts how projects are associated with their documents.
Original PR description
The `_compute_documents()` method was expecting that the `documents_folder_id` field was always set.
However, the field is not required and can be empty.
This is not an issue if the compute is called on a single record, but when called on a recordset with :
- A project with related folder with at least one document
- A project with `documents_folder_id` empty The compute will fail because it calls `startswith()` with a parameter that is `False`.
```python
File "/home/odoo/src/enterprise/19.0/documents_project/models/project_project.py", line 50, in <lambda>
document_ids = documents.filtered(lambda doc: doc.parent_path.startswith(project.documents_folder_id.parent_path))
TypeError: startswith first arg must be str or a tuple of str, not bool
```
Solution:
Check for project-related documents only if the dedicated folder is set.
Forward-Port-Of: odoo/enterprise#117066This update resolves an issue where the Point of Sale (POS) wouldn't open correctly when reloading in offline mode. The fix ensures data is properly handled during offline reloads, and updated tests confirm the POS can now be reloaded successfully while offline. This improves the user experience and reliability of the POS system.
Original PR description
Currently when reloading the POS while offline the POS does not open despite all data being stored in IndexedDB. This is because some of the data fetching functions were not properly handling the offline case. Modified tests to ensure that the POS can be reloaded while offline. Also modified the tour offline_util so it handles page refresh. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260590
This update fixes a layout issue on the shop grid for users viewing the website in RTL (Right-to-Left) languages. The changes adjust borders and padding to ensure the shop layout appears correctly, providing a better user experience for a wider range of customers. This ensures consistent and accurate product display for all users.
Original PR description
Prior to this commit, the shop grid layout was broken in RTL due to misplaced left borders and padding. This commit adjusts those elements for RTL, fixing the layout. task-5933289 | Before | After | |--------|--------| | <img width="1406" height="869" alt="Screenshot 2026-05-04 at 10 37 56" src="https://github.com/user-attachments/assets/81f057cc-89d3-44f6-a723-9b439b88290d" /> | <img width="1392" height="877" alt="Screenshot 2026-05-04 at 10 36 53" src="https://github.com/user-attachments/assets/ded4eb4a-c82d-4114-ade6-5455f341a8f5" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262483
This update resolves an issue where the cursor would incorrectly appear after an image block after deleting content. The fix prevents the system from misinterpreting self-closing elements, ensuring the cursor remains before the image as intended. This improves the user experience when editing content with images.
Original PR description
After a deletion, if the selection would end up on an image and the image is considered as a block, the selection is set inside it. Upon collapse, this leads to having the selection after the image. This commit avoids this by preventing `normalizeEnterBlock` from taking self closing elements into account. Steps to reproduce: - Go to website - Drop a `s_text_image` snippet - Select the image - Press the left cursor key to put the cursor before the image - Type a letter - Press backspace - Type a letter => The second letter was put after the image task-5436148 Forward-Port-Of: odoo/odoo#263543
This update fixes a bug that occurred when users tried to reschedule marketing activities within a campaign. The change prevents errors related to activity hierarchy updates, ensuring campaigns run smoothly and reliably. It also simplifies the process to avoid user mistakes when testing campaigns.
Original PR description
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the…
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save - An error will be thrown **Issue:** The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: `base_dt_str = trace.parent_id.schedule_date or trace.parent_id.mailing_trace_ids[0].write_date or trace.participant_id.create_date` **Fix:** Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-5362978 Forward-Port-Of: odoo/enterprise#107556
This update fixes an issue where PDF Manager action names appeared awkwardly due to a styling class. The change removes this class, resulting in cleaner and more professional-looking action names within the PDF Manager interface. This improves the user experience and overall presentation.
Original PR description
Previously, pdf_manager actions used class "text-uppercase". Action names looked awkward. In this commit, we remove the class and properly display action names. task-6159317 Forward-Port-Of: odoo/enterprise#117000 Forward-Port-Of: odoo/enterprise#116382
This update resolves an issue where file boxes, even when fully selected and deleted, weren't removed from the To-Do creation screen. The fix allows deletion of non-editable file boxes if their parent is editable, ensuring a cleaner user experience. This improves the overall usability of the HTML editor.
Original PR description
Problem: When adding a file box, selecting all content, and deleting, the file box is not removed. Cause: `o_file_box` is non-editable, so `canBeDeleted` returns `false` for this node, preventing its deletion. Solution: Allow deletion of non-editable nodes when they are fully selected and their parent is editable. Steps to reproduce: - Go to To-Do → Create New. - Upload a file. - Type some text next to the file. - Select all content (Ctrl + A or with the mouse). - Press Backspace/Delete multiple times. - Observe that the file box is not removed. task-6185206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263008
A recent bug in the Odoo sale_expense module prevented users from correctly searching for customers when adding expenses. This fix corrects a technical error related to how domain expressions were used, ensuring the search function now works as intended. This resolves a potential issue where users couldn't accurately record expenses.
Original PR description
**PROBLEM** & operator must be used with 2 Domain. https://github.com/odoo/odoo/pull/206894 forget to convert the right side part to a domain, leading to a traceback. 1. Install sale and expense_sale. 2. Set the Sales/Sales permission to "User: Own Documents only". 3. Create an expense of type communication. 4. On the field "costumer to reinvoice", start typing to search. 5. A traceback will occur. opw-612755 Forward-Port-Of: odoo/odoo#263861
This update corrects a bug in the payroll calculation for Colorado-based employees. Previously, the system incorrectly generated a positive CO State Income Tax amount. This fix aligns with established payroll tax rules, ensuring accurate withholding and preventing potential refund issues.
Original PR description
## Issue When generating a payslip for an employee of a company located in Colorado, the *CO State Income Tax* could end up positive. ## Steps to reproduce 1. Install *United States - Payroll*…
## Issue
When generating a payslip for an employee of a company located in Colorado, the *CO State Income Tax* could end up positive.
## Steps to reproduce
1. Install *United States - Payroll* (`l10n_us_hr_payroll`)
2. Set the current company's State to Colorado
3. Create an employee and a contract
- Wage: $0
- (Set the contract's status to *Running*)
- (In the payroll tab) State Withholding Allowance: $1000
4. Create a Payslip for the employee
- Structure: *"United States: Regular Pay"*
5. Compute Sheet
6. **In the _Salary Computation_ tab, the _CO State Income Tax_ line has a positive value**
## Justification
This fix is similar to the one applied for the AL(abama) state income tax by https://github.com/odoo/enterprise/commit/f0eeb55f1e3cf965c6a409675813d4a699e5fca6. That modification was justified by CAS (PO of US localizations for Payroll) in opw-5137280:
> *"Payroll taxes are always funds withheld from employee's paychecks, if there is a positive value it means the tax is a refund, not a withholding. Refunds happen when individuals file their income."*
## Note to reviewer
The test [`test_069_al_state_tax_0_income`](https://github.com/odoo/enterprise/blob/219d2a797ee2099c9d77c2defc9c9c5e1d504ffe/test_l10n_us_hr_payroll_account/tests/test_salary_rules.py#L957-L989) (added by the aforementioned commit https://github.com/odoo/enterprise/commit/f0eeb55f1e3cf965c6a409675813d4a699e5fca6) is wrongly indented and thus never executed. The test passes with the dedicated fix, and fails without it, as expected. Let me know if you want me to indent it correctly (in this commit or in an additional one).
opw-5999856
Forward-Port-Of: odoo/enterprise#116653
Forward-Port-Of: odoo/enterprise#1127241 change
Resolved issues and error corrections
This update resolves issues preventing Odoo's Norwegian VAT XML exports from passing government validation checks. The changes ensure accurate decimal formatting, correct mathematical calculations, and the inclusion of required legal notes, allowing businesses to file their VAT returns correctly and avoid delays. This fix directly addresses compliance requirements with Skatteetaten.
Original PR description
Before commit: The Norwegian VAT XML export fails Skatteetaten validation due to incorrect decimal formatting, mathematical rounding mismatches between base and tax amounts, missing mandatory legal…
Before commit: The Norwegian VAT XML export fails Skatteetaten validation due to incorrect decimal formatting, mathematical rounding mismatches between base and tax amounts, missing mandatory legal notes, and invalid KID number formats. Fix: To strictly follow Skatteetaten validation rules for the Norway VAT XML, the following changes were implemented: - Ensured standard rates drop the decimal (e.g, `25.0` to `25`), and formatted fractional rates like `11.11` to `11,11` in XML. - Rounded down the `tax_amount` to align precisely with government mathematical expectations. - `base_amount` converted into absolute value to ensuring the calculation (`base * rate = tax`) resolves perfectly. - Add the mandatory `<merknad>` explaining the reverse charge method for codes 81, 83, 86, 88, and 91. - Clean the `company_kid` by safely stripping the 'NO' prefix, and 'MVA' suffix. Expect: The generated XML payload now adheres perfectly to Skatteetaten's strict structural and mathematical rules, allowing the VAT return to pass government validations successfully. Related Community PR: https://github.com/odoo/odoo/pull/258390 Task-6033027 Forward-Port-Of: odoo/enterprise#116962 Forward-Port-Of: odoo/enterprise#110792
2 changes
Resolved issues and error corrections
This update corrects a display issue where certain quality point types were incorrectly shown regardless of the selected operations. The fix ensures these types are only visible when a manufacturing operation is selected and a work order operation is defined, improving data accuracy and usability.
Original PR description
**Steps to reproduce:** - Install `quality_control` and `mrp` modules with demo data - Go to Quality → Quality Points → Create(New) - In the `Type` field, observe that options such as 'Print Label',…
**Steps to reproduce:**
- Install `quality_control` and `mrp` modules with demo data
- Go to Quality → Quality Points → Create(New)
- In the `Type` field, observe that options such as
'Print Label', 'Register Production', etc. appear
regardless of the selected `Operations`
**Issue**:
Types like `print_label`, `register_production`,
`register_byproducts`, and `register_consumed_materials`
are displayed even when the Operations is not
Manufacturing and when no work order operation is defined.
**Expected behavior**:
These `types` should only be available when:
- `Operations` Type = Manufacturing
- `work order operation` is set
**Cause**:
The custom search logic for the `allow_registration` boolean field
relied on receiving a direct `True` or `False` value.
https://github.com/odoo/enterprise/blob/de3682c7f50b68c19d3a3429fa3768c447074f50/mrp_workorder/models/quality.py#L104
Before `saas-18.3`, the `value` passed to the domain search method was
a plain boolean(True/False).
https://github.com/odoo/enterprise/blob/de3682c7f50b68c19d3a3429fa3768c447074f50/mrp_workorder/models/quality.py#L21-L24
Starting from `saas-18.3`, the value is passed as
`OrderedSet([True])`. while the operator received is `in`
or `not in`.
Because the value always arrives `OrderedSet([True])`,
the condition checking the `value` is always
evaluated as truthy. As a result, the code never reaches the
else branch of the logic, which causes the incorrect domain
behavior.
The issue is caused by how Odoo optimizes boolean domains.
When we pass:
('allow_registration', '=', False)
the value correctly reaches the base domain logic as
`allow_registration = False`.
But during domain processing at:
https://github.com/odoo/odoo/blob/347c46f8ecff7ae97c2a686bf5750374b6c3e2d3/odoo/orm/domains.py#L967
it optimize it to:
('allow_registration', 'in', [False])
Then `_optimize()` is called, which again calls
`_optimize_step()`:
https://github.com/odoo/odoo/blob/347c46f8ecff7ae97c2a686bf5750374b6c3e2d3/odoo/orm/domains.py#L459
Inside `_optimize_step()` at:
https://github.com/odoo/odoo/blob/347c46f8ecff7ae97c2a686bf5750374b6c3e2d3/odoo/orm/domains.py#L971
it is further simplified to:n ('allow_registration', 'not in', [True])
Similarly, when we pass: ('allow_registration', '=', True)
it becomes: ('allow_registration', 'in', [True])
This is expected behavior.
The custom search method for `allow_registration`
was not handling these optimized forms correctly,
which caused Issue.
**FIX:**
- Use the domain `operator (in / not in)` to determine the intended
boolean condition instead of relying on the received value(OrderedSet([True])).
- This is correct because Odoo normalizes boolean domains to only two
forms during optimization: in [True] and not in [True]. Therefore,
the operator reliably indicates whether the condition expects
True or False, allowing the search method to handle the domain
correctly.
---
opw-5915197This update fixes an issue where portal messages were incorrectly restricted, preventing certain message types from being visible to users. The change expands the visibility of non-internal messages while still hiding internal notes as intended. This ensures all users can access relevant portal communications.
Original PR description
*: test_mail_full Since #138233, portal messages were strictly filtered by the `mt_comment` subtype. This was intended to hide internal notes, but it incorrectly excluded other non-internal message subtypes. Basically we want the share domain (`_get_search_domain_share()`) to apply to all users in the portal. This change ensures internal notes remain hidden while allowing all other non-internal non-comment subtypes to be visible. opw-6031571 Forward-Port-Of: odoo/odoo#263914 Forward-Port-Of: odoo/odoo#263052
4 changes
Resolved issues and error corrections
This update fixes an issue where discount lines in VAT reports were incorrectly calculated. The previous system incorrectly converted negative discount values to positive, leading to inflated report totals. The fix ensures accurate reporting by only flipping the sign of account balances when credits are issued.
Original PR description
Step to reproduce: - install l10n_cz_reports_2025 and switch to cz company - create a invoice, with cz company ( as partner), of 100. - when adding products, add "Transaction code" (optional fields) to "Goods" - Add discount line, set to -10, add "Transaction code" in this line too. - confirm it Observation: - invoice is 90$ - open vies summary report for this year - value turn out to 110 Cause: - commit [1](https://github.com/odoo/enterprise/commit/892268c44b1bbc838a9f03ef36a079bfff625ca6) converts every balance to +ve and only negate it, in case of refund - in case of discount lines, price is -ve, ABS() turn it to +ve and value comes out to be wrong Fix: - instead of applying ABS() directly, we flip the signs only for out_* moves, in short when a account is credited, its balance is < 0 then we flip its sign opw- 5979262 Forward-Port-Of: odoo/enterprise#116990 Forward-Port-Of: odoo/enterprise#113087
This update resolves an issue where users were receiving an error message when exporting payroll data to SDWorx for freelance employees. The change removes a redundant check for SDWorx codes specifically for freelancers, streamlining the export process. This ensures accurate data transfer for all employee types.
Original PR description
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set…
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set the Employee Type to Freelancer from HR Settings page. 4. Navigate to Payroll > Reporting > Export Work Entries to SDWorx Observation: ------------------------------- A user error is raised stating: ``` There is no SDWorx code defined for the following employees ``` Issue: ------------------------------- In https://github.com/odoo/enterprise/pull/106065/changes/c19009c776349c3f5d8aebf99aff8efe987b54db The Check for Freelance Employee type was removed, which was earlier added in the fix https://github.com/odoo/enterprise/pull/102211/changes/96724c3cc55725e87e618443b96069921b8f3bda Solution: ------------------------------- Add a condition to the employee filter to exclude freelance employees from the SDWorx code validation. opw-5387342 Forward-Port-Of: odoo/enterprise#114411
This update resolves an issue where the general ledger CSV export occasionally failed due to errors handling currency data. Specifically, it corrected a problem with integer formatting and an exclusion of inactive currencies, ensuring reliable and accurate CSV exports for financial reporting.
Original PR description
Follow-up to 8dfe4c0, addressing four issues in `_generate_csv_lazy_export`: 1. `AttributeError: 'int' object has no attribute 'id'` when `col['currency']` is a raw integer on aggregate lines returned by `_get_lines` with `no_format=True`. 2. `KeyError` on `decimal_places_per_cur_id` when a foreign currency account uses an inactive currency. The currency lookup was built with the default `active_test=True`, excluding archived currencies. opw-5994050 Forward-Port-Of: odoo/enterprise#114896 Forward-Port-Of: odoo/enterprise#112500
A bug was causing users to be redirected to the wrong document view after completing a signature request. This update corrects the redirection logic by directing users back to their list of signatures on the portal, simplifying the process and ensuring accurate navigation. This resolves a usability issue for users signing documents.
Original PR description
steps : - create a signature request with 2 roles, assign those to demo or portal user - create another one with a single signature role assigned to the demo or portal user - go on the portal and click on the second document to sign it - complete the document then click close on the thank you popup -> you are redirected on the portal view of the first document This happens because the redirect to /my/document is made using the sign_request id but the controller is using a sign_request_item id. Instead of adding a confusing controller route to be able to pass sign_request ids to reach the document's portal page, we simply redirect to the list of signatures on the portal instead. opw-6190390 Forward-Port-Of: odoo/enterprise#116600
18 changes
Resolved issues and error corrections
This update addresses a critical issue where Odoo transactions could leave incorrect tax records with Avalara. By committing Avalara's actions after the initial Odoo transaction, we prevent 'ghost' invoices and ensure accurate tax reporting. Accountants will now receive alerts if issues arise, allowing for quick resolution.
Original PR description
Some flows post an invoice and then perform additional work that may fail or at least delay the database commit (e.g. `_cron_post_process()` on `payment.transaction`). This extra work can raise…
Some flows post an invoice and then perform additional work that may fail or at least delay the database commit (e.g. `_cron_post_process()` on `payment.transaction`). This extra work can raise standard Odoo exceptions, and even without them, concurrent transactions or database deadlocks are possible. The invoice is committed on Avalara's side within `_post()`, so a later rollback of the Odoo transaction leaves a committed ghost invoice on Avalara's side. Accountants need to find these and manually void them to stop Avalara from filing incorrect tax returns. To avoid this, we move the Avalara commit into a postcommit hook. Since `account_external_tax` already calls `_get_external_taxes()` just before `_post()` to calculate taxes, the postcommit call is unlikely to fail. If it does, we log an activity on the invoice to notify the user, who will then need to resolve it manually (either by cancelling on the Odoo side and retrying, or by recreating the entry directly in the Avalara portal). opw-6192702
This update resolves a technical error that prevented users from generating balance sheet comparisons correctly. The fix ensures that date types are consistently handled, allowing the comparison feature to function as intended. This improves the reliability of balance sheet reporting.
Original PR description
Step to reproduce - Install the accountant module. - create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it - Navigate to Accounting > Report > Balance Sheet - Click the…
Step to reproduce
- Install the accountant module.
- create a fiscal year (for 01/01/26 to 30/06/26) from setting and enable it
- Navigate to Accounting > Report > Balance Sheet
- Click the `Comparison` smart button and set `Previous Period` to `2 periods`.
Observation:
- we face a traceback
``` File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5739, in _get_annotations
period_date_from = self._adjust_date_for_joined_comparison(options, period_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/odoo/codebase/enterprise/saas-19.2/account_reports/models/account_report.py", line 5695, in _adjust_date_for_joined_comparison
return min(period_date_from, comparison_date_from)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<' not supported between instances of 'datetime.date' and 'str'
```
Cause:
- `_get_period_dates` return string in case we have date which falls in
`custom_range_match`, when `get_report_information` is called, while
`period_date_from` is of type date
- hence there is mismatch between types
Fix:
- `_get_period_dates` is supposed to return date object always, hence fixed the
return type in case we have match for custom range
opw-6185629
Forward-Port-Of: odoo/enterprise#116350This update simplifies a confusing error message related to GST registrations, specifically for businesses using multiple GST numbers within the same organization. The new message clearly prompts users to verify the connection between their GST username and number, reducing support requests and improving the user experience. This change enhances the reliability of the system for businesses managing multiple tax registrations.
Original PR description
Users operating with multiple GST registrations (GST-wise branches/companies) could encounter a misleading error when the GST username belonged to a different GST number within the same organization. Previously, the system raised an error directly received from the server: [AUTH4041] Invalid Parameter state-cd in request header This message was confusing and led to unnecessary support tickets and false reports, as the issue was actually a mismatch between GST username and number. The error message has been updated to be more explicit and user-friendly: Please confirm that <gst_username> is associated with <gst_number>. Additionally, refactored duplicated logic by extracting the common code into a single helper function and reusing it across all occurrences. task-6041510 Forward-Port-Of: odoo/enterprise#111115
This update resolves an issue where rapid actions triggered duplicate account return check records being created in the database. The fix prevents multiple simultaneous processes from attempting to create the same record, ensuring data integrity. This improves the stability and efficiency of the account reporting feature.
Original PR description
Issue -------------- When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to…
Issue
--------------
When refreshing checks on account returns (e.g. from rapid successive clicks or component re-renders), multiple concurrent RPC calls to `refresh_checks` were being dispatched to the server. This created a race condition that resulted in duplicate `account.return.check` records being generated in the database.
steps to reproduce demonstrated in video: https://drive.google.com/file/d/1-A0ZHdYGdv-UL0dqClqK6Kos_iVXoZai/view?usp=sharing
When this happen the `runAllReturnChecks` method fires parallel RPC calls to [`refresh_checks`](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1974-L1992) on the server. In the case of instant multiple RPC calls, parallel threads are dispatched which causes the data preparation stage to run simultaneously.
Because both threads run in parallel, Thread 2 runs its [preparation and existing ](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1986-L1987 )check mechanism before Thread 1 has reached the actual `create()` function [trigger](https://github.com/odoo/enterprise/blob/55bfd499660d3eda0abfc9e8ed8c9a2befbd394b/account_reports/models/account_return.py#L1998-L1999). Consequently, Thread 2's existence check fails to find the record (since Thread 1 hasn't committed it to the database yet), and it considers the record eligible for creation—even though the exact same record is already prepared for creation by Thread 1. This race condition leads to duplicate `account.return.check` records.
Logs to demonstrate the thread execution:
--------
```python
2026-04-16 08:30:51,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.000 0.002
2026-04-16 08:30:51,662 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.report/dispatch_report_action#account.report.dispatch_report_action HTTP/1.0" 200 - 17 0.006 0.012
2026-04-16 08:30:51,847 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:51] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 26 0.009 0.025
2026-04-16 08:30:52,099 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 95 0.029 0.064
2026-04-16 08:30:52,320 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:52] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.004
THREAD NAME: odoo.service.http.request.137360481711808 Thread ID: 137360481711808
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360481711808 -------------DATA PREPARING STAGE------------
Thread ID: 137360481711808
Thread ID: 137360481711808 RECORD EXISTING CHECK: None
2026-04-16 08:30:53,842 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:53] "GET /odoo/tax-report/tax-return?debug=1 HTTP/1.0" 200 - 29 0.020 0.021
2026-04-16 08:30:54,066 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/load_menus HTTP/1.0" 200 - 4 0.002 0.009
2026-04-16 08:30:54,351 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/manifest.webmanifest HTTP/1.0" 200 - 6 0.003 0.005
2026-04-16 08:30:54,493 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/webclient/translations?hash=bb5aa713d587cc7dd07b13d1d7efc2c525517e99&lang=en_US HTTP/1.0" 200 - 1 0.000 0.002
2026-04-16 08:30:54,586 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/bundle/web_tour.interactive?lang=en_US&debug=1 HTTP/1.0" 200 - 1 0.001 0.003
2026-04-16 08:30:54,640 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/action/load_breadcrumbs HTTP/1.0" 200 - 7 0.003 0.006
2026-04-16 08:30:54,710 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/ir.http/lazy_session_info#ir.http.lazy_session_info HTTP/1.0" 200 - 2 0.001 0.004
2026-04-16 08:30:54,753 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /bus/websocket_worker_bundle?v=19.0-2 HTTP/1.0" 304 - 3 0.004 0.006
2026-04-16 08:30:54,766 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "GET /web/image?model=res.users&field=avatar_128&id=2 HTTP/1.0" 304 - 9 0.012 0.013
2026-04-16 08:30:54,777 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /mail/data HTTP/1.0" 200 - 34 0.034 0.020
2026-04-16 08:30:54,824 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/get_views#account.return.get_views HTTP/1.0" 200 - 3 0.001 0.010
2026-04-16 08:30:54,934 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:54] "POST /web/dataset/call_kw/account.return/web_read_group#account.return.web_read_group HTTP/1.0" 200 - 88 0.029 0.051
2026-04-16 08:30:55,107 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "POST /web/dataset/call_kw/account.return/get_next_returns_ids#account.return.get_next_returns_ids HTTP/1.0" 200 - 2 0.001 0.005
THREAD NAME: odoo.service.http.request.137360513177280 Thread ID: 137360513177280
REFRESH CHECK START:--------------------------------------------
Thread ID: 137360513177280 -------------DATA PREPARING STAGE------------
Thread ID: 137360513177280
Thread ID: 137360513177280 RECORD EXISTING CHECK: None
2026-04-16 08:30:55,589 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:55] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.006
2026-04-16 08:30:56,702 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:56] "GET /web/service-worker.js HTTP/1.0" 200 - 1 0.000 0.003
2026-04-16 08:30:58,893 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:30:58] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.006 0.023
2026-04-16 08:31:05,296 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:05] "GET /websocket?version=19.0-2 HTTP/1.0" 400 - 1 0.001 0.002
Thread ID: 137360481711808 DATA to_create: 168
Thread ID: 137360481711808 done process create
2026-04-16 08:31:10,132 14 INFO bsra_4165887_upg werkzeug: 202.131.97.106 - - [16/Apr/2026 08:31:10] "POST /web/dataset/call_kw/account.return/refresh_checks#account.return.refresh_checks HTTP/1.0" 200 - 513 11.611 6.039
Thread ID: 137360513177280 DATA to_create: 168
Thread ID: 137360513177280 done process create
```
- OPW: 5917459
Forward-Port-Of: odoo/enterprise#114045This update corrects a technical issue that was causing errors in the MRP Work Order Kanban module. The fix ensures that JavaScript classes are correctly defined within the core MRP module, resolving a runbot error. This improves the stability and reliability of the work order Kanban interface.
Original PR description
js_class defined in mrp_workorder should have been defined in mrp. This solves runbot error 242288 Forward-Port-Of: odoo/enterprise#117036
This update fixes an issue where newly created stock batches were incorrectly named 'New' instead of following the standard BATCH/<TYPE>/000NN naming convention. The fix ensures batches are automatically named correctly, improving data consistency and reporting accuracy. This resolves a minor operational inefficiency.
Original PR description
Steps to reproduce 1. Open the Barcode app > Operations > Delivery Orders. 2. Switch to the "Batches" tab. 3. Create a new one. Issue The created batch keeps the placeholder name "New" instead of…
Steps to reproduce
1. Open the Barcode app > Operations > Delivery Orders.
2. Switch to the "Batches" tab.
3. Create a new one.
Issue
The created batch keeps the placeholder name "New" instead of being
renamed to `BATCH/<TYPE>/000NN`.
The barcode kanban "New" button calls `open_new_batch_picking`, which
runs `Batch.create({})` while the action context carries
`default_picking_type_id` set by `stock.picking.type._get_action` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock/models/stock_picking.py#L432.
Since `vals` itself doesn't carry `picking_type_id`, the lookup in
`stock.picking.batch.create()` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock_picking_batch/models/stock_picking_batch.py#L181
returns an empty recordset, so the sequence-based rename branch is
skipped and the name stays at the field default `'New'`. The
subsequent `super().create` then applies the context default, so the
batch is correctly linked to a picking type but with the wrong name.
opw-6168320
Forward-Port-Of: odoo/enterprise#115809This update corrects a display issue where the 'Reconnect Bank' button appeared incorrectly when account online consent hadn't expired. The fix ensures the button only shows when a consent expiration date is present, preventing confusion and unnecessary actions. This improves the user experience and data accuracy.
Original PR description
Since this commit 375516ccfd20d3a969c532376d0ba9db195b35fd, the reconnect bank button is displayed when the account online link doesn't have consent expiration date, which is wrong, if the consent doesn't expire, we shouldn't display the button. Why this happens? Because we don't check if expiring_synchronization_date is falsy, we only check if expiring_synchronization_due_day <= 0, which is always true in this case, has the compute set 0 as a fallback value. no-task Forward-Port-Of: odoo/enterprise#117101
This update resolves a technical issue preventing proper display of the employee form within the South Africa (SA) localization. The fix ensures that the employee record view functions correctly for users in the SA region, improving data accuracy and usability. This resolves a previously reported problem impacting SA-based users.
Original PR description
this commit fixes the broken view of employee form in SA localization. task-6205661 Forward-Port-Of: odoo/enterprise#117027
This update resolves an error that prevented users from marking payslips as paid when the 'Include Unpaid' option was selected. The change ensures that the system correctly processes unpaid payslips, preventing a technical error and improving the reliability of the payroll reporting feature. This fix addresses a potential disruption to payroll processing.
Original PR description
Currently, an error occurs when a user attempts to mark a payslip as paid. **Steps to Reproduce:** - Install the `hr_payroll` module without demo data. - Go to `Payslips` and click on `New…
Currently, an error occurs when a user attempts to mark a payslip as paid. **Steps to Reproduce:** - Install the `hr_payroll` module without demo data. - Go to `Payslips` and click on `New Off-cycle`. - Create a record > `Compute` > `Validate`, and Pay. - In the wizard, enable `Include Unpaid` and select `CSV` mode. - Click `Mark as Paid`. **Error:** `UnboundLocalError: cannot access local variable 'rows' where it is not associated with a value` The error occurs when a user tries to mark a payslip as paid with Include Unpaid enabled. When the wizard is created from here [1], the default unpaid payslips are empty. In this case, the system assigns an empty set of payslips to process [2].and the rows variable is not defined because there are no payslips to work on, which raises the error [3]. This commit ensures that when the wizard is created, the matched unpaid payslips are passed to the wizard. If the Include Unpaid option is enabled, the unpaid payslips are assigned for processing, similar to [4]. The unpaid payslips cannot be empty, as they always include the currently processed payslip. Also, the rows are redefined for each payslip case and updated accordingly. Therefore, this commit ensures that the rows are created at the end from grouped payments. [1] https://github.com/odoo/enterprise/blob/a784d118e076724b02e5c59d9ce5d1815c42b0bf/hr_payroll/models/hr_payslip.py#L792-L809 [2] https://github.com/odoo/enterprise/blob/e971fca0d09e564ae9029f3d7e166e078c44dcbb/hr_payroll/wizard/hr_payroll_payment_report_wizard.py#L56 [3] https://github.com/odoo/enterprise/blob/e971fca0d09e564ae9029f3d7e166e078c44dcbb/hr_payroll/wizard/hr_payroll_payment_report_wizard.py#L97 [4]: https://github.com/odoo/enterprise/blob/a784d118e076724b02e5c59d9ce5d1815c42b0bf/hr_payroll/models/hr_payslip_run.py#L274-L288 sentry-7436885639 Forward-Port-Of: odoo/enterprise#116787 Forward-Port-Of: odoo/enterprise#115090
This update optimizes the Odoo interface for smaller screens by removing the VoIP icon from the systray when it's not in use. This improves the overall user experience and reduces visual clutter, particularly on devices with limited screen space.
Original PR description
task-5079952
This update resolves a technical error that prevented the system from correctly identifying project documents when the designated folder was not specified. The fix ensures the system functions smoothly regardless of whether a folder is associated with a project, improving document retrieval reliability.
Original PR description
The `_compute_documents()` method was expecting that the `documents_folder_id` field was always set.
However, the field is not required and can be empty.
This is not an issue if the compute is called on a single record, but when called on a recordset with :
- A project with related folder with at least one document
- A project with `documents_folder_id` empty The compute will fail because it calls `startswith()` with a parameter that is `False`.
```python
File "/home/odoo/src/enterprise/19.0/documents_project/models/project_project.py", line 50, in <lambda>
document_ids = documents.filtered(lambda doc: doc.parent_path.startswith(project.documents_folder_id.parent_path))
TypeError: startswith first arg must be str or a tuple of str, not bool
```
Solution:
Check for project-related documents only if the dedicated folder is set.
Forward-Port-Of: odoo/enterprise#117066This update refines how Odoo automatically matches bank statements to invoices. Previously, it prioritized the closest date, which wasn't always accurate. Now, it only matches if there's a single bank statement prior to the statement line's date, ensuring more reliable reconciliation.
Original PR description
Before this pr, we decided that when there was multiple candidates, we would take the one closer to the date of the statement line but it is not always what we want. We decided to change that so that it would match only if there is one candidate prior the date of the statement line. Exemple: Invoice 1 the 10/06 and invoice 2 the 20/06 → Payment the 05/06 → no matching (0 before) → Payment the 15/06 → match with invoice 1 (only 1 before) → Payment the 25/06 → no matching (More than 1 invoice open before) task-6143809 Forward-Port-Of: odoo/enterprise#115888 Forward-Port-Of: odoo/enterprise#115284
This update resolves an issue where setting a maximum package weight in Sendcloud caused rate calculations to fail. The fix ensures that shipments are correctly split into packages based on weight limits, preventing errors when requesting shipping rates. This improves the accuracy of shipping cost estimations.
Original PR description
Issue ----- Putting a max weight on a package type causes getting a rate with Sendcloud to fail. Steps to reproduce ----- - Setup Mondial Relay using Sendcloud - Set a default package type with max…
Issue ----- Putting a max weight on a package type causes getting a rate with Sendcloud to fail. Steps to reproduce ----- - Setup Mondial Relay using Sendcloud - Set a default package type with max weight 2kg - Create a product with a 500g weight - Create a SO with the product - Add delivery - Sendcloud Mondial Relay - Get rate > Impossible to get a rate Cause ----- When retrieving the shipping method to use when retrieving a rate, we use the real weight of the order. https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L67 https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L81 However, when making the rate call, we use the value returned by `_split_shipping` https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L91 which is equal to the maximum weight of the package. This is blocking in some cases, like if - the real weight is 750g - the package max is 2kg - Sendcloud returns a shipping method for [500g;1kg] Asking a rate for this method & a 2kg package will fail (rightfully so). Solution ----- The shipment should be split into packages before retrieving the shipping methods. Otherwise the problem might be the other way around where we retrieve a shipping method for the whole order, only to split it into multiple packages because they don't fit in one. Also, the `shipping_weight` returned by `_split_shipping` should only be different from the order's total weight if it is higher than the maximum deliverable weight. ----- Ticket: opw-5947199 Forward-Port-Of: odoo/enterprise#116909 Forward-Port-Of: odoo/enterprise#108315
This update fixes an issue preventing accurate translation exports from the web studio's interactive editor. The problem stemmed from a formatting error in template strings that caused incorrect code extraction. By removing problematic formatting, the system now correctly exports and applies translation messages, improving the overall translation workflow.
Original PR description
It seems that the Babel Javascript tokenizer is not able to correctly parse a template string starting with a backslash and a newline. This caused it to extract pieces of code coming after it. The code excerpts would be exported in the POT file, but not applied to the JS code of course. The original message was not exported though, so it was not possible to translate it. This commit rewrites the template string to not use a backslash and a newline. This way the string is properly extracted and the code after it is not. Change was introduced by this commit[^1]. [^1]: https://github.com/odoo/enterprise/commit/56a2d9c4c2cc655af0469038d4c483581ac78864 Forward-Port-Of: odoo/enterprise#116927
This update fixes a recurring issue where Odoo would repeatedly retry sending eTIMS transactions, leading to an error (924). The change improves reliability by intelligently handling network interruptions and ensuring that invoice numbers are correctly tracked, preventing duplicate attempts and improving data accuracy for Kenyan e-invoicing.
Original PR description
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already…
When the network drops after eTIMS processes a transaction but before Odoo receives the confirmation, Odoo would retry with the same invoice number, causing eTIMS error 924 (Invoice number already exists). For POS orders, the old code decremented the sequence on any error (including timeout), so the next retry consumed the same invcNo. If eTIMS had already recorded the original send, the retry was rejected with 924. Fix by introducing a fetch-first strategy: on retry, if a pending invcNo is found in l10n_ke_order_json, call selectInvoiceDetails before sending. If eTIMS already has the invoice, recover the receipt data directly without resending. If eTIMS does not have it, resend with the same invcNo safely. On timeout errors, the sequence is no longer decremented so the invcNo is preserved in l10n_ke_order_json for the next idempotent retry. For customer invoices, the existing fetch-first logic only bailed out on TIM (timeout) errors, falling through on CON (connection) errors and retrying blindly. Additionally, if saveTrnsSalesOsdc returned 924, there was no recovery path and the invoice number would be cleared. Fix by also bailing on CON in the fetch block, and adding an explicit 924 handler that calls selectInvoiceDetails to recover the existing receipt instead of failing. opw-6105693 Forward-Port-Of: odoo/enterprise#115649
This update resolves an issue where the table number on the kitchen display was being cut off when the order title exceeded a certain length. This prevented kitchen staff from quickly identifying the correct table, leading to potential delays. The change has been reverted to ensure the table number is always fully visible.
Original PR description
**Steps to reproduce:** - Download the German language - Set the restaurant to QR + Ordering - Set the Service at Table, pay after each order - Set the language to German - Go to the Self and order…
**Steps to reproduce:** - Download the German language - Set the restaurant to QR + Ordering - Set the Service at Table, pay after each order - Set the language to German - Go to the Self and order something while the language is German - Chose table 12 - Go to the kitchen display - The title is truncated, meaning we can't see the table number **Why the fix:** If the title is more than 150px it will be truncated and "..." will replace the table number. This has been introduced in ed5b010dc7b5c11bbbc8513c1edb0ec4f58778c1 but not being able to see the table number might be bad as some people would need to spend time trying to figure out which table the order is for, instead of just having to look at the kitchen display. We now revert this change to break to a new line in the case where the card title is too long, so we can always see the table number. Before: <img width="317" height="156" alt="image" src="https://github.com/user-attachments/assets/25e76026-bdad-4639-9dfc-0d75ffa8d8c8" /> Afer: <img width="329" height="174" alt="image" src="https://github.com/user-attachments/assets/f387dd5f-96d3-4148-bc76-215393c76e67" /> opw-6096111 Forward-Port-Of: odoo/enterprise#116594 Forward-Port-Of: odoo/enterprise#114859
This update resolves an issue where the barcode scanning feature wasn't accurately updating inventory quantities when scanning pack-in-pack items. The fix ensures that quantities are correctly recorded during inventory counts, improving the reliability of stock tracking. This resolves a problem preventing accurate inventory updates.
Original PR description
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent…
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent package PP as container - Inventory > Operations > Adjustments > Physical Inventory - Select you product line for A > Request a count (from the control panel button) - Enable Show Expected Quantity and confirm - Go to the barcode app > Count Inventory (1) - scan your parent package PP #### > traceback: Uncaught Promise > Cannot create property 'inventory_quantity' on boolean 'false' ### Cause of the issue: When the Package scan is processed, we loop over all quants related to it: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L566-L569 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L602-L617 And for each of these we try to find an existing line representing the quant to update or we do create a new line. Now, the issue, is that the subpackages of the quant are not provided to find the quant candidate line to update. As such, no line is found we enter the else clause and try to createa a NewLine: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L617-L627 This time however, the appropriate subpackage (the one of the quant) is provided to the arguments. And, since the line representing this quant is already existing, the `_createNewLine` will return False: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L393-L399 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L423 This leads to a traceback at the end of the else close since `false.inventory_quantity` doe not make sense (Cannot create property 'inventory_quantity' on boolean 'false') https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L626-L627 Fix: We adapt the `_processPackage` of the `BarcodeQuantModel` to mimic the existing 'update' behavior on the `BarcodePickingModel`: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_picking_model.js#L2110-L2133 Note that UOM converstion should not be required since quants are already uniformly expressed in the product uom: https://github.com/odoo/odoo/blob/30b4edace6b0859cb1b1ba4f7f2ea80ba5398e3d/addons/stock/models/stock_quant.py#L52-L54 opw-5864591 Forward-Port-Of: odoo/enterprise#116715
This update fixes a bug that occurred when users tried to reschedule marketing activities, specifically within automated campaigns. The change prevents errors related to missing parent information, ensuring campaign scheduling functions reliably. This improves campaign stability and reduces potential disruptions for users.
Original PR description
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the…
**Steps to reproduce:** - Create a new marketing campaign with two activities - Set them to occur some number of days after the beginning - Save the campaign and start it - Modify one of the activities to occur some number of days after the other activity and save - Modify the child activity by changing the number of days after its parent that it should run and save - An error will be thrown **Issue:** The trace related to the child activity has no parent when trying to reschedule it in `_update_schedule_date`. This causes an issue when trying to get the first mailing_trace_ids using index 0 in this line: `base_dt_str = trace.parent_id.schedule_date or trace.parent_id.mailing_trace_ids[0].write_date or trace.participant_id.create_date` **Fix:** Prevent the activity hierarchy to be modified on started campaigns. We also change the indexing to avoid further out of range issue and properly default on the participant create value. Trying to match existing traces to their parents has too many edge cases when trying to avoid duplicates, and might often need to reset the whole trace chain to work properly. This approach avoids user mistakes on running campaigns, but if a user tries to launch a test (even on draft campaign) he won't be able to modify the hierarchy further without deleting/recreating some activities/traces. So we should ignore this for test traces, but it could impact the behavior between test and actual executions. opw-5362978 Forward-Port-Of: odoo/enterprise#107556
3 changes
Resolved issues and error corrections
This update fixes an issue where newly created stock batches were incorrectly named 'New' instead of following the standard BATCH/<TYPE>/000NN naming convention. The change ensures that all new batches are automatically named correctly, improving data consistency and reporting accuracy. This resolves a minor operational inefficiency.
Original PR description
Steps to reproduce 1. Open the Barcode app > Operations > Delivery Orders. 2. Switch to the "Batches" tab. 3. Create a new one. Issue The created batch keeps the placeholder name "New" instead of…
Steps to reproduce
1. Open the Barcode app > Operations > Delivery Orders.
2. Switch to the "Batches" tab.
3. Create a new one.
Issue
The created batch keeps the placeholder name "New" instead of being
renamed to `BATCH/<TYPE>/000NN`.
The barcode kanban "New" button calls `open_new_batch_picking`, which
runs `Batch.create({})` while the action context carries
`default_picking_type_id` set by `stock.picking.type._get_action` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock/models/stock_picking.py#L432.
Since `vals` itself doesn't carry `picking_type_id`, the lookup in
`stock.picking.batch.create()` at
https://github.com/odoo/odoo/blob/f768f276171b079a76324d40307db385f558dda6/addons/stock_picking_batch/models/stock_picking_batch.py#L181
returns an empty recordset, so the sequence-based rename branch is
skipped and the name stays at the field default `'New'`. The
subsequent `super().create` then applies the context default, so the
batch is correctly linked to a picking type but with the wrong name.
opw-6168320
Forward-Port-Of: odoo/enterprise#115809This update resolves an issue where users were receiving an error message when exporting payroll data to SDWorx for freelance employees. The change removes a redundant check for SDWorx codes specifically for freelancers, streamlining the export process. This ensures accurate data transfer for all employee types.
Original PR description
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set…
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set the Employee Type to Freelancer from HR Settings page. 4. Navigate to Payroll > Reporting > Export Work Entries to SDWorx Observation: ------------------------------- A user error is raised stating: ``` There is no SDWorx code defined for the following employees ``` Issue: ------------------------------- In https://github.com/odoo/enterprise/pull/106065/changes/c19009c776349c3f5d8aebf99aff8efe987b54db The Check for Freelance Employee type was removed, which was earlier added in the fix https://github.com/odoo/enterprise/pull/102211/changes/96724c3cc55725e87e618443b96069921b8f3bda Solution: ------------------------------- Add a condition to the employee filter to exclude freelance employees from the SDWorx code validation. opw-5387342 Forward-Port-Of: odoo/enterprise#114411
This update fixes an issue where the remaining balance wasn't accurately displayed when multiple foreign currency transactions were selected in the accounting dashboard. The change ensures that the correct balance is always shown, regardless of how many transactions are selected, improving accuracy and reliability of financial reporting.
Original PR description
Steps to reproduce: - company currency EUR - Copy the bank journal and define the USD as a currency - Create and confirm two invoices for Customer A for a total amount X - Go to the Accounting Dashboard and select the new journal - Create a new transaction of an amount Y > X - Select 1 of the invoices - Select the second one Issue: When selecting one transaction line, the correct balance is displayed. When selecting multiple lines in the foreign currency journal, the balance changes to “/” instead of showing the actual balance. opw-6168097
6 changes
Resolved issues and error corrections
This update optimizes a key query in our Point of Sale system, resulting in significantly faster report generation. By adding the journal to the search criteria, the system now leverages an existing database index, dramatically reducing the time it takes to retrieve account move information. This improves the overall performance and responsiveness of the POS system.
Original PR description
Currently the query to get the closing difference account move is done by searching for the reference of the move, which is not very efficient. This commit optimizes this query by adding the journal…
Currently the query to get the closing difference account move is done by searching for the reference of the move, which is not very efficient. This commit optimizes this query by adding the journal to the search criteria, which allows us to benefit from the index on the journal_id field. Here is an example of the before after on a database with 39 million account_move records. Meanwhile only 10-20K account_move are linked to specific journals used in POS payment methods. All measures are performed with a warmed up cache [Explain Before](https://explain.dalibo.com/plan/h8edf56c09d7dfd7) ### Benchmark: <table> <thead> <tr> <th># of am</th> <th>Before</th> <th>After</th> </tr> </thead> <tbody> <tr> <td>38982635</td> <td>~17s</td> <td>~22ms</td> </tr> </tbody> </table> [Explain After](https://explain.dalibo.com/plan/be2397f176a6b29d) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262148
This update resolves an issue where users were incorrectly receiving an error message when exporting payroll data to SDWorx for freelance employees. The change removes a redundant check for SDWorx codes specifically for this employee type, streamlining the export process. This ensures accurate data transfer for all employee types.
Original PR description
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set…
Steps to reproduce: ------------------------------- 1. Install `l10n_be_hr_payroll_sd_worx` module 2. Switch the active company to a Belgian company 3. Go to Employees and create a new employee. Set the Employee Type to Freelancer from HR Settings page. 4. Navigate to Payroll > Reporting > Export Work Entries to SDWorx Observation: ------------------------------- A user error is raised stating: ``` There is no SDWorx code defined for the following employees ``` Issue: ------------------------------- In https://github.com/odoo/enterprise/pull/106065/changes/c19009c776349c3f5d8aebf99aff8efe987b54db The Check for Freelance Employee type was removed, which was earlier added in the fix https://github.com/odoo/enterprise/pull/102211/changes/96724c3cc55725e87e618443b96069921b8f3bda Solution: ------------------------------- Add a condition to the employee filter to exclude freelance employees from the SDWorx code validation. opw-5387342 Forward-Port-Of: odoo/enterprise#114411
This update resolves a technical issue that was causing database errors when calculating membership states. The fix uses a more robust method within Odoo's database system to handle empty data, preventing the error. This ensures the membership system functions correctly and reliably.
Original PR description
SQL `IN %s` clause failed due to an empty tuple, causing a syntax error. By switching to `read_group`, the ORM handles empty domains gracefully. This also improves maintainability by using standard API methods instead of direct cursor execution. opw-6196166 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264030
This update strengthens the signup process by ensuring all email addresses entered during registration are validated. Previously, users could enter any string, creating a potential security risk. The change enforces email format validation and adds autocomplete attributes to the signup form for a better user experience.
Original PR description
**Problem**
Before this commit, the email address typed in the signup form was not validated. Consequently, the user could use whatever string as email address.
**How to reproduce**
1. Activate "free sign up" ("Settings"->"Website"->"Customer Account")
2. While being signed off, navigate to "/web/signup"
3. No validation is enforced on the email field
**Fix**
The email field is correclty marked as "required", but its type was set as "text" instead of "email". This commit fixes the problem by changing the type to "email".
task-6094631
Forward-Port-Of: odoo/odoo#258967This update fixes a discrepancy in how contract types are defined within Odoo's HR modules. Specifically, the contract type ID was standardized across modules to ensure consistency and prevent potential errors. This change improves data accuracy and stability within the HR contract management system.
Original PR description
[IMP] hr_contract_salary: fix contract_type_id definition The definitions of the contract_type_id in hr_contract_salary_offer and l10n_be_hr_contract_salary/hr_contract_salary_offer should be same I converted the definition of contract_type_id in the base module to the Belgium one. Also, the contract_type_id was inserted to the view in Belgium one as well, I deleted that part to prevent double appearance. This task is only for v.17, after this version I will open a new PR to handle them. Do not forward the task after v.17 (only for v.17) task - 6101717 Forward-Port-Of: odoo/enterprise#113244
This update resolves an issue where a command used to check for updates on IoT boxes was causing unexpected upgrades. The change now skips the upgrade process if the command fails, ensuring updates only occur as intended and preventing disruptions to IoT Box systems.
Original PR description
If `git ls-remote origin <db_branch>` randomly fails, we assume `db_branch` is `master`. It was useful for devs in the past, but now lead to update to Trixie on IoT Boxes 25_07 and previous, which is unwanted in such circumstances. We now skip upgrade if `db_branch` is `master`. Forward-Port-Of: odoo/odoo#264126
1 change
Resolved issues and error corrections
This update resolves an issue where marking a payslip batch as paid would fail if multiple salary lines or input lines used the same code (like 'OTHERFEES'). The fix allows for successful batch payment even with multiple line items sharing the same code, ensuring accurate payroll processing for Swiss employees.
Original PR description
Current behavior: When marking a payslip batch as paid, a ValueError "Expected singleton" is raised if a salary attachment and a manually added input line use the same code (e.g., OTHERFEES).…
Current behavior: When marking a payslip batch as paid, a ValueError "Expected singleton" is raised if a salary attachment and a manually added input line use the same code (e.g., OTHERFEES). Expected behavior: Batch should be marked as paid successfully even when multiple salary lines and multiple input lines share the same code. Required Modules - l10n_ch_hr_payroll_elm - l10n_ch (Switzerland - Accounting) - l10n_ch_hr_payroll (Switzerland - Payroll) - l10n_ch_hr_payroll_account (Switzerland - Payroll with Accounting) - l10n_ch_hr_payroll_elm (Switzerland - Payroll ELM Standard) - l10n_ch_reports (Switzerland - Accounting Reports) Steps to reproduce: 1. Activate the Payroll app 2. Install the required Swiss payroll modules listed above 3. Go to Payroll > Configuration > Salary Rules and create a new rule: Name: Other Fees Code: OTHERFEES Category: Allowance Salary Structure: Switzerland: Regular Pay Active: Yes Appears on Payslip: Yes Condition Based on: Python Expression Python Condition: result = 'OTHERFEES' in inputs Amount Type: Python Code Python Code: result = inputs['OTHERFEES'].amount and result_name = inputs['OTHERFEES'].name 4. Go to Payroll > Configuration > Salary Attachment Types and create a new type: Name: Other Fees Code: OTHERFEES Country: Switzerland 5. Go to Payroll > Contracts > Salary Attachments and create an attachment: Employee: (select an employee) Type: Other Fees (the one you just created) Description: e.g., "Parking" Monthly Amount: e.g., $70.00 Start Date / End Date: set dates that cover your payslip period State: Running 6. Go to Payroll > Payslips > All Payslips and create a new payslip: Select the employee from step 5 Set the period to match your salary attachment dates Add the payslip to a batch Save and verify the salary attachment appears automatically in "Other Inputs" 7. In the "Other Inputs" section, add a second line: Click "Add a line" Create a new Other Input Type with code OTHERFEES (e.g., "Other Fees - Just Created") Set a description (e.g., "Dining") and amount (e.g., -99) You should now have TWO input lines both using code OTHERFEES 8. Click "Compute Sheet" and verify you see TWO salary lines with code OTHERFEES in the Salary Computation tab Click "Create Draft Entry" Go to Payroll > Payslips > Batches, find your batch, and click "Mark as Paid" Expected ResultBatch is marked as paid successfully.Actual ResultValueError: Expected singleton: hr.payslip.line(??, ??) Cause of the issue: In _record_attachment_payment() (line 149), the code filters salary lines by code and expects a single record. When multiple lines share the same code, slip_lines contains multiple records, causing the singleton error on slip_lines.total access. Fix: Handle multiple salary lines with the same code by summing their totals/quantities instead of expecting a singleton. opw-5473648