Daily updates from Odoo
Navigate
Branch
Monday, November 3, 2025
184 changes
10 changes
Enhancements to existing features
Estonia VAT report XML exports now process large volumes of accounting entries in batches instead of recalculating each line separately. This prevents timeouts on large reporting periods and makes VAT submission exports more reliable for businesses with high transaction volumes.
Original PR description
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this…
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this resulted in excessive repeated queries and, for big datasets, timeout errors. Behavior after: Introduced _custom_unfold_all_batch_data_generator, which batches the computation of expression totals for all lines. Now, journal items are resolved in bulk and mapped back to their respective moves, significantly reducing redundant queries. The VAT XML export completes successfully, even on months with very large datasets. Root cause: The Estonia VAT report was missing a batch unfold method (_custom_unfold_all_batch_data_generator). Without it, the system executed totals computation for each line individually instead of in batch, causing major performance degradation. Benchmark: | Period size (journal items) | Before patch | After patch | |----------------------------------------|----------------------|--------------------| | ~15k | 7s | 5s | | ~200k+ | Timeout error| 21s | opw-5046077 Forward-Port-Of: odoo/enterprise#97660 Forward-Port-Of: odoo/enterprise#95047
The booking screen in the Point of Sale no longer automatically opens the keyboard on phones and tablets when it loads. This makes the screen easier to use on touch devices and avoids interrupting users with an unnecessary keyboard pop-up.
Original PR description
Task: [#5016943](https://www.odoo.com/odoo/project/1737/tasks/5016943) --- On tablets and phones, the search bar was autofocus when opening the booking screen in the POS frontend. This was causing the keyboard to open automatically, which was not a good user experience. Now the search bar is not autofocus on touch devices for the booking screen by creating a new controller to manage this. Forward-Port-Of: odoo/enterprise#96873
Resolved issues and error corrections
Fixed an issue where vendor bills containing multiple vehicles could cause the tax report to fail. Tax lines are now matched by vehicle, preventing incorrect merging and improving reliability for fleet-related accounting reports.
Original PR description
**Steps to reproduce:** 1. Install the *Fleet* and `accounting` modules. 2. Create a new purchase tax. 3. Configure the tax with a 50% repartition line for an `600000 expense` account and a 50%…
**Steps to reproduce:** 1. Install the *Fleet* and `accounting` modules. 2. Create a new purchase tax. 3. Configure the tax with a 50% repartition line for an `600000 expense` account and a 50% repartition line for a `101000 current asset` account for both income and refund. 4. Create a vendor bill with two product lines, each having a different vehicle assigned with the newly created tax in both lines. 5. Check the *Tax Report*(account>tax), including the date of this vendor bill. **Observed behavior:** * Tax lines linked to the current asset account are merged. * Tax lines linked to the expense account remain separate (since `vehicle_id` is set on the `account.move.line`). * This mismatch triggers an error in the tax report. **Root cause:** The tax details query does not account for the `vehicle_id` field when matching tax lines with base lines. As a result, tax lines are incorrectly merged across different vehicles. **Solution:** Override `_get_extra_query_base_tax_line_mapping` to include the `vehicle_id` in the matching condition, ensuring tax lines are only paired with base lines having the same `vehicle_id`. This prevents incorrect merging and resolves the report error. opw-5013757 Forward-Port-Of: odoo/odoo#232001 Forward-Port-Of: odoo/odoo#228422
This fixes an issue where items belonging to combo products could appear under the wrong combo when multiple combo quantities were changed before saving a sales order. Sales teams can now edit consecutive combo products with confidence that the order lines remain clear and correctly grouped.
Original PR description
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving,…
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving, change the quantity of the second combo. - Observe that the combo items now appear misplaced — items from the second combo are inserted before those of the first combo. Issue: - The order of combo items becomes incorrect when multiple combo products are updated consecutively in the same unsaved Sale Order. Cause: - During `onchange`, the `self.order_line` recordset reflects the *in-memory order of applied commands* rather than the database `sequence` field because they are not saved in the DB during the edition. - Each `onchange` rebuilds `order_line` using concatenated command lists (`delete + create + update`), So when multiple combos are modified without save, newly created combo items are appended according to command evaluation order — not by logical grouping. - This causes combo items to shift relative to their parent combo lines. Solution: - Restrict the recomputation of order lines to non-combo lines by filtering out combo item lines during the rebuild. As combo items will always be in their desired sequence. - This ensures that combo items always stay under their respective parent combos and their sequence is preserved, regardless of the order in which combos are updated. opw-5148770 Affected Version:18.0 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233740
Dimona-related employee fields are now displayed only for Belgian employees instead of appearing for everyone. This reduces confusion for companies operating outside Belgium and keeps employee contract screens more relevant.
Original PR description
Before this commit, the fields about dimona were shown for all employees, now these fields will be displayed only for belgian employees. task-5148931 Forward-Port-Of: odoo/enterprise#98484 Forward-Port-Of: odoo/enterprise#96496
The Cambodian accounting package now uses unique tax names to prevent installation errors when setting up the chart of accounts manually. This helps businesses using Cambodian localization complete accounting configuration reliably.
Original PR description
Fixes an issue where some taxes in the Cambodian package have the same name, leading to errors when manually installing the chart template. Interestingly enough, the constraints does not trigger on the demo data company. Task [link](https://www.odoo.com/odoo/project.task/5194444) task-5194444 Forward-Port-Of: odoo/odoo#233066 Forward-Port-Of: odoo/odoo#232968
**Steps to reproduce:** 1. Install the `website_sale` module. 2. Create a product with multiple variants. 3. Archive one of the variants. 4. Publish the product on the website. 5. Try selecting the archived variant. **Observed behavior:** * The variant appeared greyed out without any alert, leaving users without feedback. **Root cause:** * The alert element was removed in this [commit](https://github.com/odoo/odoo/commit/eac892a4ad7373d18f954afbbcd2f1213ac5f281). **Solution:** *
Original PR description
**Steps to reproduce:** 1. Install the `website_sale` module. 2. Create a product with multiple variants. 3. Archive one of the variants. 4. Publish the product on the website. 5. Try selecting the archived variant. **Observed behavior:** * The variant appeared greyed out without any alert, leaving users without feedback. **Root cause:** * The alert element was removed in this [commit](https://github.com/odoo/odoo/commit/eac892a4ad7373d18f954afbbcd2f1213ac5f281). **Solution:** * Restore the alert in the template and toggle its visibility in the JS handler. * Selecting an archived variant now displays the message: “This combination does not exist”. opw-5069059
[FIX] website: get scroll from document element for footer animation __Current behavior before commit:__ Since [this PR], the scrolling is not done on `#wrapwrap` anymore. Now when an animation is set on an element inside the footer it will not appear if a slideout effect is set on it. __Description of the fix:__ Get `scrollTop` and `scrollHeight` from the document element instead of `#wrapwrap` and add a test tour. __Steps to reproduce:__ 1. Open the Website builder. 2. Click on
Original PR description
[FIX] website: get scroll from document element for footer animation __Current behavior before commit:__ Since [this PR], the scrolling is not done on `#wrapwrap` anymore. Now when an animation is…
[FIX] website: get scroll from document element for footer animation __Current behavior before commit:__ Since [this PR], the scrolling is not done on `#wrapwrap` anymore. Now when an animation is set on an element inside the footer it will not appear if a slideout effect is set on it. __Description of the fix:__ Get `scrollTop` and `scrollHeight` from the document element instead of `#wrapwrap` and add a test tour. __Steps to reproduce:__ 1. Open the Website builder. 2. Click on a column in the footer. 3. Set an "On Appearance" Animation on it. 4. Set the footer Slideout Effect to "Slide Hover". 5. Add some content on the page so that it's needed to scroll for the footer to be visible. 6. Save. 7. Scroll to the footer. => The column doesn't appear. [this PR]: https://github.com/odoo/odoo/pull/98429 --- [FIX] website: scroll on new entry in faq horizontal __Current behavior before commit:__ Since [this PR][1], the scrolling is not done on `#wrapwrap` anymore. Now when adding a new entry to the snippet faq horizontal, the page doesn't scroll automatically to the new entry. This behavior has actually never worked because [the PR that introduced faq horizontal][2] was merged just after [the PR that moved the scrolling to the document element][1]. __Description of the fix:__ Get `scrollTop` and `scrollHeight` from the document element instead of `#wrapwrap` and add a test tour. __Steps to reproduce:__ 1. Open the Website builder. 2. Drag a Text block 3. Choose the FAQ horizontal snippet 4. Click on "Add New" => The page doesn't scroll to the new entry. [1]: https://github.com/odoo/odoo/pull/98429 [2]: https://github.com/odoo/odoo/pull/176438 Forward-Port-Of: odoo/odoo#233911 Forward-Port-Of: odoo/odoo#228396
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch
Original PR description
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which…
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch - Scan anything #### > Traceback #### Other issues: The same flow with a cancelled batch triggers the same tracebacks and, with a done batch triggers the message: "This picking is already done". ### Cause of the issue: Since `this.state.view === "barcodeLines"`, scans are processed as if we were processing an existing `BarcodePickingBatchModel` with lines: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/components/main.js#L204-L209 In particular, if the scan corresponds to a product, and error will be raised because the scan can not process a `createNewLine` for the scanned product in the current view and if the scan does not correspond to anything valid, it will raise an error because `this.picking` is undefined and `this.picking.use_existing_lots` raises an error: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/models/barcode_model.js#L1115 https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L177-L179 opw-5162164 Forward-Port-Of: odoo/enterprise#98022 Forward-Port-Of: odoo/enterprise#97526
Before this commit- We used to rely on clearbit to fetch the logo of the company on the client side After this commit- We replace it with logo.dev and remove the fetching of logo from client side and move it to the IAP task-5126337 IAP PR- https://github.com/odoo/iap-apps/pull/1234 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233925 Forward-Port-Of: odoo/odoo#231397
Original PR description
Before this commit- We used to rely on clearbit to fetch the logo of the company on the client side After this commit- We replace it with logo.dev and remove the fetching of logo from client side and move it to the IAP task-5126337 IAP PR- https://github.com/odoo/iap-apps/pull/1234 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233925 Forward-Port-Of: odoo/odoo#231397
24 changes
Enhancements to existing features
Estonia VAT report XML exports now process large sets of accounting data in batches instead of repeating the same work line by line. This prevents timeout errors on high-volume months and helps businesses complete tax reporting reliably and faster.
Original PR description
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this…
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this resulted in excessive repeated queries and, for big datasets, timeout errors. Behavior after: Introduced _custom_unfold_all_batch_data_generator, which batches the computation of expression totals for all lines. Now, journal items are resolved in bulk and mapped back to their respective moves, significantly reducing redundant queries. The VAT XML export completes successfully, even on months with very large datasets. Root cause: The Estonia VAT report was missing a batch unfold method (_custom_unfold_all_batch_data_generator). Without it, the system executed totals computation for each line individually instead of in batch, causing major performance degradation. Benchmark: | Period size (journal items) | Before patch | After patch | |----------------------------------------|----------------------|--------------------| | ~15k | 7s | 5s | | ~200k+ | Timeout error| 21s | opw-5046077 Forward-Port-Of: odoo/enterprise#97660 Forward-Port-Of: odoo/enterprise#95047
Tax brackets for pakistan localization has been updated to include the new values for 2026. Forward-Port-Of: odoo/enterprise#98345
Original PR description
Tax brackets for pakistan localization has been updated to include the new values for 2026. Forward-Port-Of: odoo/enterprise#98345
The POS configuration screen no longer automatically focuses the search bar on phones and tablets. This avoids the on-screen keyboard opening by itself, making the view easier to use on touch devices.
Original PR description
Task: [#5016943](https://www.odoo.com/odoo/project/1737/tasks/5016943)
---
On tablets and phones, the search bar was autofocus when opening the POS config kanban view. This was causing the keyboard to open automatically, which was not a good user experience.
Now the search bar is not autofocus on touch devices for the POS config kanban view ('view_pos_config_kanban').
Forward-Port-Of: odoo/odoo#231045The booking screen in Point of Sale no longer automatically focuses the search bar on phones and tablets. This prevents the on-screen keyboard from opening right away, making the experience smoother and less distracting on touch devices.
Original PR description
Task: [#5016943](https://www.odoo.com/odoo/project/1737/tasks/5016943) --- On tablets and phones, the search bar was autofocus when opening the booking screen in the POS frontend. This was causing the keyboard to open automatically, which was not a good user experience. Now the search bar is not autofocus on touch devices for the booking screen by creating a new controller to manage this. Forward-Port-Of: odoo/enterprise#96873
This update keeps Raspberry Pi and IoT device setup working with newer Python versions by replacing a removed system library. It also fixes file location handling and Wi‑Fi configuration saving so device setup and network settings continue to work correctly on newer system versions.
Original PR description
To ensure compatibility with python 3.13+, we updated the method to generate the rpi's password to avoid using the removed `crypt` lib. We also ensure that files moved between `point_of_sale/tools/posbox/`, `addons/iot_box_image/` and `setup/iot_box_builder` can still be found by system processes using symlinks. Forward-Port-Of: odoo/odoo#233813 Forward-Port-Of: odoo/odoo#233423
Resolved issues and error corrections
Product forms now show the correct tax information when a branch company uses taxes inherited from its parent company. This helps users see accurate sale prices on products, matching the taxes applied later on sales orders and invoices.
Original PR description
Steps: - Install account app. - Create a branch company under the main company. - Create a tax for the branch company. - Add a main company tax on a product. - Switch to branch company. Issue: - Tax…
Steps: - Install account app. - Create a branch company under the main company. - Create a tax for the branch company. - Add a main company tax on a product. - Switch to branch company. Issue: - Tax string is not displaying on the product form even though its setting tax from parent company on invoice line and SO line so its displaying wrong sale price on product form. Cause: - After [PR] taxes are only consider from current company even though company is branch company but in [17.0 PR] we share taxed and other accounting related data b/w main and branch company so if branch does not it's specific tax applied on product then it should take tax from its parent company. Fix: - Compute tax_string in product the way we compute tax on invoice line, SOL etc using `_filter_taxes_by_company` method this way it'll give proper tax which will be applied on related documents. [PR]: https://github.com/odoo/odoo/pull/194881 [17.0 PR]: https://github.com/odoo/odoo/pull/125642 opw-5042833 Forward-Port-Of: odoo/odoo#233720
This fix updates the Cambodian accounting localization so tax names are no longer duplicated. It prevents errors when businesses manually install the Cambodian chart of accounts, making setup more reliable.
Original PR description
Fixes an issue where some taxes in the Cambodian package have the same name, leading to errors when manually installing the chart template. Interestingly enough, the constraints does not trigger on the demo data company. Task [link](https://www.odoo.com/odoo/project.task/5194444) task-5194444 Forward-Port-Of: odoo/odoo#232968
The Point of Sale settlement flow now checks that a customer still exists before calculating their outstanding balance. This prevents sessions from crashing when a customer was deleted while the session was still open, improving reliability for store staff.
Original PR description
Currently, a missing exception is triggered when reopening a PoS session after a partner is deleted. **To reproduce this issue:** 1) Install point_of_sale and pos_settle_due. 2) Open a PoS session 3)…
Currently, a missing exception is triggered when reopening a PoS session after a partner is deleted. **To reproduce this issue:** 1) Install point_of_sale and pos_settle_due. 2) Open a PoS session 3) Create a customer and place an order with payment. 4) Without closing the session, go to the backend. 5) Delete the customer from Contacts. 6) Reopen the previously opened PoS session. **Error:** A `missing record` exception is triggered. **Cause:** When the user reopens a PoS session after deleting a partner, the method `setAllTotalDueOfPartners` is triggered during setup. https://github.com/odoo/enterprise/blob/7c6ba26970698cb60121157c2cca0e414d5b62a0/pos_settle_due/static/src/app/services/pos_store.js#L7-L9 https://github.com/odoo/enterprise/blob/7c6ba26970698cb60121157c2cca0e414d5b62a0/pos_settle_due/static/src/app/services/pos_store.js#L44-L48 This method makes an RPC call to `get_all_total_due` to update all partners' due amounts. Since the partner was deleted, this causes a missing record exception. https://github.com/odoo/enterprise/blob/7c6ba26970698cb60121157c2cca0e414d5b62a0/pos_settle_due/models/res_partner.py#L28-L32 **Solution:** Before calling `get_total_due`, verify the partner still exists in the database. Related Community PR:- https://github.com/odoo/odoo/pull/219809 opw-4897814 Forward-Port-Of: odoo/enterprise#90596
Customers linked to Point of Sale orders can no longer be deleted while they are still needed by an open PoS session. This prevents reopening a session from failing with missing customer data and helps keep sales records consistent.
Original PR description
Currently, a partner can be deleted even if they have associated PoS orders. This causes inconsistent behavior, such as missing record tracebacks when reopening a PoS session. **To reproduce this…
Currently, a partner can be deleted even if they have associated PoS orders. This causes inconsistent behavior, such as missing record tracebacks when reopening a PoS session. **To reproduce this issue:** 1) Install point_of_sale and pos_settle_due. 2) Open a PoS session 3) Create a customer and place an order with payment. 4) Without closing the session, go to the backend. 5) Delete the customer from Contacts. 6) Reopen the previously opened PoS session. **Error:-** A `missing record` exception is triggered. **Cause:** - Starting from SaaS-18.1, PoS supports offline mode with limited functionality, due to this commit: https://github.com/odoo/odoo/pull/184417/commits/711e248efd54500f91acfb1b9a30f48177c34925 - Before this commit, data was reloaded whenever a session was opened or reopened, ensuring proper synchronization with the backend. - After this commit, IndexedDB is used to cache data and it is reused every time the session is reopened. - When the user reopens a PoS session after deleting a partner, the method `setAllTotalDueOfPartners` is triggered during setup. - This method makes an RPC call to `get_all_total_due` to update all partners due amounts. Since the partner was deleted, this causes a missing record exception. **Solution:** - Prevent users from deleting a partner who has PoS orders and an open session. - Before calling `get_total_due`, verify the partner still exists in the database. Related Enterprise PR:- https://github.com/odoo/enterprise/pull/90596 opw-4897814 Forward-Port-Of: odoo/odoo#219809
The Saudi e-invoicing address form now labels the second street/address line as “District” instead of “Street 2”. This helps users enter the correct district or borough information required for Saudi e-invoicing compliance and reduces the risk of data entry mistakes.
Original PR description
## Before this commit The `street2` field on `res.company` and `res.partner` was mapped to `cac:AccountingSupplierParty/cac:Party/cac:PostalAddress/cbc:CitySubdivisionName`, but its placeholder displayed `Street 2…`. This caused confusion among users, as they assumed it referred to `cbc:AdditionalStreetName`, leading to incorrect data entry and potential non-compliance. ## After this commit The placeholder of the `street2` field has been changed from `Street 2…` to `District…`, clarifying that this field represents the city subdivision (district or borough) of the Seller/Customer, in line with the Saudi Arabia e-invoicing specification. > Task-4951545 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#231676 Forward-Port-Of: odoo/odoo#231160
The Journal Report now updates its Global Tax Summary amounts when users change the rounding unit. This keeps tax summary figures consistent with the rest of the report and prevents confusion from mixed number formats.
Original PR description
Currently when users change the rounding unit filter in the Journal Report, the Global Tax Summary values remain in the old format instead of updating to reflect the new rounding setting. This…
Currently when users change the rounding unit filter in the Journal Report, the Global Tax Summary values remain in the old format instead of updating to reflect the new rounding setting. This creates inconsistency where main report values update correctly but tax summary values stay unchanged. Cause: - The issue occurs because `_format_column_values` method in `account_report.py` wasn't handling the special tax summary data structures (`tax_report_lines` and `tax_grid_summary_lines`) that store pre-formatted values. These structures need to be reformatted when rounding unit changes, but the formatting logic only covered standard report columns. Fix Applied: - Updated frontend (`filters.js`) to call `format_column_values_from_client` via `dispatch_report_action` instead of calling `format_column_values` directly. (this enables proper routing through the custom handler system) - Added `format_column_values_from_client` override in `JournalReportCustomHandler` that intercepts the formatting call and applies special handling for tax summary lines by adding logic to reformat `tax_report_lines` and `tax_grid_summary_lines` monetary fields using their `_no_format` counterparts. - The custom handler then delegates to the base method via `report.format_column_values_from_client()` to format standard columns. - Also added missing `_no_format` fields in `account_journal_report.py` for `base_amount` and `tax_amount` to enable proper reformatting. Forward-Port-Of: odoo/enterprise#98508 Forward-Port-Of: odoo/enterprise#94660
Fixed an issue where updating multiple combo products on an unsaved sales order could move combo items under the wrong combo. Sales teams can now adjust combo quantities with confidence that the order lines remain correctly grouped before saving.
Original PR description
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving,…
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving, change the quantity of the second combo. - Observe that the combo items now appear misplaced — items from the second combo are inserted before those of the first combo. Issue: - The order of combo items becomes incorrect when multiple combo products are updated consecutively in the same unsaved Sale Order. Cause: - During `onchange`, the `self.order_line` recordset reflects the *in-memory order of applied commands* rather than the database `sequence` field because they are not saved in the DB during the edition. - Each `onchange` rebuilds `order_line` using concatenated command lists (`delete + create + update`), So when multiple combos are modified without save, newly created combo items are appended according to command evaluation order — not by logical grouping. - This causes combo items to shift relative to their parent combo lines. Solution: - Restrict the recomputation of order lines to non-combo lines by filtering out combo item lines during the rebuild. As combo items will always be in their desired sequence. - This ensures that combo items always stay under their respective parent combos and their sequence is preserved, regardless of the order in which combos are updated. opw-5148770 Affected Version:18.0 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233740
Barcode scans are now ignored when a draft, cancelled, or completed batch transfer is opened in a context where scanning cannot be processed. This prevents confusing error messages and system tracebacks, giving warehouse users a smoother experience in the barcode app.
Original PR description
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which…
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch - Scan anything #### > Traceback #### Other issues: The same flow with a cancelled batch triggers the same tracebacks and, with a done batch triggers the message: "This picking is already done". ### Cause of the issue: Since `this.state.view === "barcodeLines"`, scans are processed as if we were processing an existing `BarcodePickingBatchModel` with lines: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/components/main.js#L204-L209 In particular, if the scan corresponds to a product, and error will be raised because the scan can not process a `createNewLine` for the scanned product in the current view and if the scan does not correspond to anything valid, it will raise an error because `this.picking` is undefined and `this.picking.use_existing_lots` raises an error: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/models/barcode_model.js#L1115 https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L177-L179 opw-5162164 Forward-Port-Of: odoo/enterprise#98022 Forward-Port-Of: odoo/enterprise#97526
This fixes Belgian payroll so public holidays during long-term sick leave are no longer paid after the legally required 30-day period. It helps ensure payslips follow Belgian rules and avoids overpaying employees in these specific absence cases.
Original PR description
Bug: In Belgium, after 30 calendar days of sick leave, all public holidays during the sick leaves are no longer paid. But here they were still being paid. Cause: The method that was checking what to do about public holidays was never seeing public holidays since they were already changed to their corresponding work entries at the work entry generation. Fix: Add the public holidays in the context and change the condition for checking if the current leave is actually from a public holiday or not. Task: 3864585 Forward-Port-Of: odoo/enterprise#98388 Forward-Port-Of: odoo/enterprise#95178
Dimona-related employee fields are now shown only for Belgian employees instead of appearing for everyone. This reduces confusion for companies operating in multiple countries and keeps payroll screens focused on relevant local requirements.
Original PR description
Before this commit, the fields about dimona were shown for all employees, now these fields will be displayed only for belgian employees. task-5148931 Forward-Port-Of: odoo/enterprise#98484 Forward-Port-Of: odoo/enterprise#96496
1. We didn't met one of the specific requirement of the BIS3 invoices to be sent through Chorus Pro. > The SIRET number for the final recipient, behind Chorus Pro should always be sent in the following tag: Invoice/cac:AccountingCustomerParty/PartyLegalEntity/CompanyID 2. One of the attributes of the CompanyID was set to schemeName which is not a valid attribute of the Peppol BIS3 specification. Fixed in 18.0+: https://github.com/odoo/odoo/commit/c3ae4b29c51c7b0cff11aac5f4bf4aab5fad16c
Original PR description
1. We didn't met one of the specific requirement of the BIS3 invoices to be sent through Chorus Pro. > The SIRET number for the final recipient, behind Chorus Pro should always be sent in the following tag: Invoice/cac:AccountingCustomerParty/PartyLegalEntity/CompanyID 2. One of the attributes of the CompanyID was set to schemeName which is not a valid attribute of the Peppol BIS3 specification. Fixed in 18.0+: https://github.com/odoo/odoo/commit/c3ae4b29c51c7b0cff11aac5f4bf4aab5fad16c9 task-none (possible opw-4972189, but might not be the only problem) Source: <img width="787" height="673" alt="image" src="https://github.com/user-attachments/assets/2a410fa8-572a-4738-aa5d-764e91271880" /> https://www.pagero.com/onboarding/aife/aife-en Forward-Port-Of: odoo/odoo#233648 Forward-Port-Of: odoo/odoo#229014
### Issue: Given a specific configuration, the `SwitchCompanyMenu` will not display all the companies a user can access. Suppose we have a company hierarchy with the following: `Company 1 > Company 2 > Company 3` (where 2 is a branch of 1, and 3 is a branch of 2). If a user has access to C1 and C3, but not C2, the menu selector will only display C1, rather than a hierarchy of all 3 companies with C2 disabled. This menu has been improved between versions, but the logic behind how we determine
Original PR description
### Issue: Given a specific configuration, the `SwitchCompanyMenu` will not display all the companies a user can access. Suppose we have a company hierarchy with the following: `Company 1 > Company 2…
### Issue: Given a specific configuration, the `SwitchCompanyMenu` will not display all the companies a user can access. Suppose we have a company hierarchy with the following: `Company 1 > Company 2 > Company 3` (where 2 is a branch of 1, and 3 is a branch of 2). If a user has access to C1 and C3, but not C2, the menu selector will only display C1, rather than a hierarchy of all 3 companies with C2 disabled. This menu has been improved between versions, but the logic behind how we determine which companies to display remains consistent. We loop over each root company from `companyService.allowedCompaniesWithAncestors`, add it, and then add its children. Depending on whether the child company is accessible, it will be disabled (but still displayed) in the hierarchy list. `companyService` pulls its company information from the `session['user_companies']` dict that is created from `session_info`. For each of the `allowed_companies`, we build the `child_ids` from the intersection of each `user.company_id.child_ids` and `user.company_ids`. So we only add the child if it itself is an allowed company, which C2 would not be. C1 is now considered a root company with no children in our loop, so C2 is skipped. C2 isn't a root company either, so it will never be seen, and therefore neither will C3. ### Solution: A similar case was addressed in #138942, where given the same company hierarchy as above, the user instead has access to C2 and C3, but not C1. This PR adjusted how we build the `child_ids` for `disallowed_ancestor_companies` (C1 in this case), properly setting the children for us to loop through. We can use this same logic for the `child_ids` of `allowed_companies`, ensuring we can properly loop through the disallowed children of allowed companies. Additionally, we need to adapt the `CompanySelector` component, which previously grabbed all children even if they were disallowed. opw-4880477 Forward-Port-Of: odoo/odoo#228438 Forward-Port-Of: odoo/odoo#217001
Problem: Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`). Cause: In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the referenced sibling was connected to the live DOM (`.isConnected`). When that check failed, the fallback was `parent.append()`. On some Firefox versions, mutation events list the parent removal *after* its children’s, meaning the parent is reinserted first while the children’s siblings still exist b
Original PR description
Problem: Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`). Cause: In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the…
Problem:
Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`).
Cause:
In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the referenced sibling was connected to the live DOM (`.isConnected`).
When that check failed, the fallback was `parent.append()`. On some Firefox versions, mutation events list the parent removal *after* its children’s, meaning the parent is reinserted first while the children’s siblings still exist but are detached. Because `.isConnected` returned false, the fallback `append()` misplaced nodes and broke the order.
Example (processed in reverse order):
```js
[
{ type: 'remove', id: 'p', parentId: 'root', node: { tagName: 'P' } },
{ type: 'remove', id: 'b1', parentId: 'p', nextId: 'b2',
node: { textValue: 'b' } },
{ type: 'add', id: 'b1', append: 'x', node: { textValue: 'b' } },
{ type: 'remove', id: 'c1', parentId: 'p', node: { textValue: 'c' } },
{ type: 'add', id: 'c1', append: 'x', node: { textValue: 'c' } },
]
```
During revert:
- Child removals (b1, c1) are processed first.
- Their sibling nodes exist but are detached → .isConnected false.
- Fallback append() used → "b" inserted after "c" → acb.
- `<p>` restored last with children in wrong order.
Solution:
Remove the `.isConnected` condition.
`before()` and `after()` work even on detached nodes, preserving the original child order regardless of browser mutation sequence.
Steps to reproduce:
- Open todo.
- Have this:
```html
<p>a[]</p>
<p>b<br>c</p>
```
- Press Delete.
- Observe "b" and "c" are not in the right order.
opw-5139795
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#233582This test was not awaiting each step properly, which becomes visible when the runbot is overloaded and the querySelector calls return null, at which point accessing `click` or `value` would trigger a traceback. runbot-161423 Forward-Port-Of: odoo/odoo#233900
Original PR description
This test was not awaiting each step properly, which becomes visible when the runbot is overloaded and the querySelector calls return null, at which point accessing `click` or `value` would trigger a traceback. runbot-161423 Forward-Port-Of: odoo/odoo#233900
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of
Original PR description
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra…
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of the screen where the search bar is located (in div .o_control_panel). The issue is that in barcode there is another element where the button to scan is located (o_kanban_tip_filter), and since the image is absolutely positioned relative to the top rather than this element, it ends up overlapping the button and the text, preventing interaction. ### Why the fix: The solution we chose is to change the position of the image to relative, for the image to not hide the text. Another possible solution was to make the image (more specifically .o_view_nocontent .o_nocontent_help) ignore all input, allowing them to go through the image and reach the button below. opw-5123880 Forward-Port-Of: odoo/enterprise#98243
Steps to Reproduce: 1. Add a Countdown snippet. 2. Change the layout to Boxes. 3. Apply a background color to the layout. 4. Hover over the delete button in the color picker. 5. A traceback error occurs. Issue: A traceback error occurs because the does not have a default value assigned. This is necessary for the snippet to preview correctly when no additional color is applied. Fix: Assign a default value to ensure that the hover behavior works properly, even when no color is set.
Original PR description
Steps to Reproduce: 1. Add a Countdown snippet. 2. Change the layout to Boxes. 3. Apply a background color to the layout. 4. Hover over the delete button in the color picker. 5. A traceback error occurs. Issue: A traceback error occurs because the does not have a default value assigned. This is necessary for the snippet to preview correctly when no additional color is applied. Fix: Assign a default value to ensure that the hover behavior works properly, even when no color is set. The issue was produced here: https://github.com/odoo/odoo/commit/03c552690b15#diff-a0262b81bb090b8c62afbd342b2a30f054cf353a35f9fc0ceeb0f86b7b9cd645 task-4752497 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232094 Forward-Port-Of: odoo/odoo#224012
Steps to reproduce the current behaviour: - Update the DEMO user to be a website "restricted editor" and sales "admin" who cannot bypass HTML field sanitization. - As ADMIN, add a YouTube video to a product page > Save. - As DEMO, try to update the content on the product page > You cannot (a dialog informs you that you cannot edit the content because an admin edited it previously). Explanation: Starting from [1], an HTML field can be flagged as `sanitize_overridable` which all
Original PR description
Steps to reproduce the current behaviour: - Update the DEMO user to be a website "restricted editor" and sales "admin" who cannot bypass HTML field sanitization. - As ADMIN, add a YouTube video to a…
Steps to reproduce the current behaviour: - Update the DEMO user to be a website "restricted editor" and sales "admin" who cannot bypass HTML field sanitization. - As ADMIN, add a YouTube video to a product page > Save. - As DEMO, try to update the content on the product page > You cannot (a dialog informs you that you cannot edit the content because an admin edited it previously). Explanation: Starting from [1], an HTML field can be flagged as `sanitize_overridable` which allowed users with the `base.group_sanitize_override` group to skip the HTML field sanitize process. If such users added some content that is not considered "sanitize friendly" (e.g. YouTube iframe), a restricted user won't be allowed to add content in the fields, since the sanitizer will remove the original content from the DOM. For this case, the code from [2] added an implementation to consider the field as none editable and warn the user once he tries to update it. Implementation: The goal of this commit it to fix the current limitation for video upload that currently prevents non admin users to edit a website record once an admin adds a video on it... The idea of the fix is the following: - We already have a technical fallback when uploading a video to save the iframe `src` to an attribute: `data-oe-expression`. - The public widget is now destroying the video iframes so they are never saved in the DOM. - A non-lazy code will build the iframes immediately on page load. - The public widget can always create the iframes if they are not already created (for compatibility). [1]: https://github.com/odoo/odoo/commit/cf844e34dd0ce4830eb99fd0fa5b6b9cb58c867c [2]: https://github.com/odoo/odoo/commit/cb80c15d3db49ede3c93171abcaa9064b88822c6 task-3757205 Forward-Port-Of: odoo/odoo#232871 Forward-Port-Of: odoo/odoo#175717
This is a feedback from a partner at OXP, he wants to know the number of activities (late or not) linked to some Lead -> activities grouped by res_id. But grouping a pivot by a many2one_reference is currently not supported. This commit adds the support. Note that carelessly grouping by a many2one_reference mixes records linked to different models (same id, but different model). To avoid mixin apples and oranges, you have to either groupby model, *then* by res_id, or add the model t
Original PR description
This is a feedback from a partner at OXP, he wants to know the number of activities (late or not) linked to some Lead -> activities grouped by res_id. But grouping a pivot by a many2one_reference is currently not supported. This commit adds the support. Note that carelessly grouping by a many2one_reference mixes records linked to different models (same id, but different model). To avoid mixin apples and oranges, you have to either groupby model, *then* by res_id, or add the model to the domain. Task: 5102923 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#231994 Forward-Port-Of: odoo/odoo#227939
This fix stops the system from trying to create product feeds for websites that would immediately exceed the allowed product limit. It prevents a migration error and helps affected databases upgrade smoothly without hitting an unnecessary validation failure.
Original PR description
``` File /home/odoo/src/odoo/saas-18.4/addons/website_sale_product_feed/models/product_feed.py, line 105, in _check_product_limit raise ValidationError(feed.env._( odoo.exceptions.ValidationError: A…
```
File /home/odoo/src/odoo/saas-18.4/addons/website_sale_product_feed/models/product_feed.py, line 105, in _check_product_limit
raise ValidationError(feed.env._(
odoo.exceptions.ValidationError: A single feed cannot contain more than 5,000 products. Please separate products with Categories.
```
```
(Pdb) feed.env['product.product'].search_count(feed._get_feed_product_domain())
12433
```
During migration I am getting the traceback mentioned above, which is occurring because [here](https://github.com/odoo/odoo/blob/saas-18.3/addons/website_sale_product_feed/__init__.py#L14) we have populated feed records in _post_init_hook which will create feed records without any [category ID](https://github.com/odoo/odoo/blob/saas-18.3/addons/website_sale_product_feed/models/website.py#L21) because of which, [here](https://github.com/odoo/odoo/blob/saas-18.3/addons/website_sale_product_feed/models/product_feed.py#L101) we get all records without a category, which is of course higher than our soft limit of 5000, and a validation error occurs: the customer database does not have GMC enabled. Still, it calls _populate_product_feeds, which is why I have moved it to a condition.
opw-5180407
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr6 changes
Enhancements to existing features
Tax brackets for pakistan localization has been updated to include the new values for 2026. Forward-Port-Of: odoo/enterprise#98345
Original PR description
Tax brackets for pakistan localization has been updated to include the new values for 2026. Forward-Port-Of: odoo/enterprise#98345
Resolved issues and error corrections
The Planning app now shows the recurrence banner only after recurring shifts have actually been created. This avoids confusing users with an early banner that does not yet apply to any generated shifts.
Original PR description
**Steps to reproduce:** --------- 1. Create a shift. 2. Save the shift. 3. Open the shift and enable the recurrence. 4. Observe that the recurrence banner is immediately displayed. **Issue:** ----- The recurrence banner is shown as soon as a shift is marked recurring, even though no recurring shifts have been generated yet. This is misleading since the banner has no effect until the actual recurrence slots exist. **Cause:** ------- The banner visibility was based on repeat and id, so it appeared too early, before any recurring shifts were actually created. **Fix:** -------- Update the banner visibility condition to check for both repeat and recurrency. Now, the recurrence banner only appears once the recurrence record exists and recurring shifts are generated: task-5163851 Forward-Port-Of: odoo/enterprise#97245
Before this commit, the fields about dimona were shown for all employees, now these fields will be displayed only for belgian employees. task-5148931 Forward-Port-Of: odoo/enterprise#98484 Forward-Port-Of: odoo/enterprise#96496
Original PR description
Before this commit, the fields about dimona were shown for all employees, now these fields will be displayed only for belgian employees. task-5148931 Forward-Port-Of: odoo/enterprise#98484 Forward-Port-Of: odoo/enterprise#96496
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of
Original PR description
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra…
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of the screen where the search bar is located (in div .o_control_panel). The issue is that in barcode there is another element where the button to scan is located (o_kanban_tip_filter), and since the image is absolutely positioned relative to the top rather than this element, it ends up overlapping the button and the text, preventing interaction. ### Why the fix: The solution we chose is to change the position of the image to relative, for the image to not hide the text. Another possible solution was to make the image (more specifically .o_view_nocontent .o_nocontent_help) ignore all input, allowing them to go through the image and reach the button below. opw-5123880 Forward-Port-Of: odoo/enterprise#98243
This change reverts a previous adjustment that disabled automatic focus on certain mobile POS screens. The issue was later fixed globally elsewhere, so this revert avoids keeping a temporary workaround that is no longer needed.
Original PR description
Task: [#5016943](https://www.odoo.com/odoo/project/1737/tasks/5016943) Revert PR: - [odoo/231045](https://github.com/odoo/odoo/pull/231045) - [enterprise/96873](https://github.com/odoo/enterprise/pull/96873) --- The purpose of this task was to remove the autofocus for certain views concerning the POS on mobile devices. However, this is no longer needed, since the root of the issue was global and had to be fixed across all views. While this task addressed the issue on a few specific views, [PR #232054](https://github.com/odoo/odoo/pull/232054) provides a global fix. Forward-Port-Of: odoo/enterprise#98494
This fix keeps subscription delivery fees as fixed charges when invoices are prorated. It prevents shipping costs from being reduced by the subscription timing, which avoids incorrect billing for customers using delivery products.
Original PR description
Version - 18.0 Steps to reproduce: 1. Create a subscription with delivery product. 2. Select align to calendar in the recurring plan 2. Add shipping method by assigning a delivery product with recurring_invoice. 3. Create an invoice with prorated Issue: - Delivery products are considered service-type products and their price was prorated in invoice. Cause: - The proration logic treated delivery lines like normal recurring service products, instead of keeping their fixed charge. Solution: - Exclude delivery products from proration by setting their period ratio to 1. Co-authored-by: Darshan Patel dvpa@odoo.com Co-authored-by: Federico Braidi brfe@odoo.com task-4662188 Forward-Port-Of: odoo/enterprise#91133
26 changes
Enhancements to existing features
This update removes use of an outdated page rendering instruction from the system. It helps keep the platform aligned with current standards and reduces the risk of future compatibility issues, with little expected day-to-day impact for users.
Original PR description
task-4461090
Payroll CSV payment reports now include payment lines for partners linked to company contribution salary rules. This helps ensure employer-side contributions are visible in payment exports, reducing missed or incomplete payroll-related payments.
Original PR description
- For CSV payment reports, add lines for partners defined as company contributions in salary rule configurations. - Ensures that company-side contributions are properly reflected in generated payment reports. Task: 5114655
Demo employee payroll data for India now uses the correct employee pay category and regular pay structure. Two sample payslips are also marked as paid, making the demo data better reflect realistic payroll workflows.
Original PR description
-Update the Pay Category of all demo data employees to "India: Employee Pay". -Update "India: Regular" Pay Structure on all the Demo Payslip Records. -Mark two payslips in the demo data as "Paid".
The POS booking screen no longer automatically opens the search field on tablets and phones. This prevents the on-screen keyboard from appearing unexpectedly, making booking navigation smoother for mobile users.
Original PR description
Task: [#5016943](https://www.odoo.com/odoo/project/1737/tasks/5016943) --- On tablets and phones, the search bar was autofocus when opening the booking screen in the POS frontend. This was causing the keyboard to open automatically, which was not a good user experience. Now the search bar is not autofocus on touch devices for the booking screen by creating a new controller to manage this. Forward-Port-Of: odoo/enterprise#96873
Belgian payroll settings now start benefit fields at 0 instead of pre-filled maximum values, helping users make more deliberate choices. Added placeholders and help tips make the settings easier to understand and reduce configuration mistakes.
Original PR description
* Updated the default values of Belgian benefits to 0 instead of the previous maximum. * Added placeholders and tooltips to several fields to improve user guidance. * Adapted the tests by manually adding benefits so that the calculated salary values match the expected results (the previous expected results were based on the old default values). Task-5135523 (https://www.odoo.com/odoo/project/1251/tasks/5135523)
Resolved issues and error corrections
Lithuanian payslips no longer apply the employee pension contribution twice when the pension accumulation option is enabled. This helps ensure payroll deductions match expected contribution rules and reduces the risk of overcharging employees.
Original PR description
**Issue**
When generating a payslip for an employee with the `l10n_lt_pension` setting enabled on the contract ("Participate to pension accumulation system"):
- the SSC is raised from 19.5% to 22.5%
- a 3% pension contribution ("Pension Scheme") is added This effectively doubles the expected contribution.
Various sources (e.g. https://taxsummaries.pwc.com/lithuania/individual/other-taxes) seem to show this is not correct.
opw-5067664
Forward-Port-Of: odoo/enterprise#98276
Forward-Port-Of: odoo/enterprise#95880This fix ensures payroll runs only check payslips that actually have issues before listing those issues. It prevents incorrect issue handling when a pay run contains a mix of problematic and normal payslips, helping payroll teams review exceptions accurately.
Original PR description
Commit e4e573e1219f38561ae74e2086cee6d54cda6f46 introduced a bug. Steps to reproduce: - Generate a payrun with at least two payslips: one with an issue and another without any issue This commit fixes the issue by filtering the issues payslips before getting their issues. task-5230921
The Planning shift recurrence banner no longer appears immediately after recurrence is enabled. It now shows only after recurring shifts have actually been created, avoiding misleading guidance for users.
Original PR description
**Steps to reproduce:** --------- 1. Create a shift. 2. Save the shift. 3. Open the shift and enable the recurrence. 4. Observe that the recurrence banner is immediately displayed. **Issue:** ----- The recurrence banner is shown as soon as a shift is marked recurring, even though no recurring shifts have been generated yet. This is misleading since the banner has no effect until the actual recurrence slots exist. **Cause:** ------- The banner visibility was based on repeat and id, so it appeared too early, before any recurring shifts were actually created. **Fix:** -------- Update the banner visibility condition to check for both repeat and recurrency. Now, the recurrence banner only appears once the recurrence record exists and recurring shifts are generated: task-5163851 Forward-Port-Of: odoo/enterprise#97245
This change restores the Documents integration for Recruitment because the action to create job applicants from documents is still needed. It prevents users from losing an existing recruitment workflow while allowing future cleanup to be handled separately.
Original PR description
As create applicant action is still needed. Further development could be done to clean the module in a more proper way later if needed. This reverts commit dd38c92a337661b30731ed32f4ae0c0e146a7e8c. Task-5090259
Barcode scans are now ignored when a batch transfer is still being created or is not in a state where scanning should apply. This prevents confusing errors and incorrect messages for warehouse users who open draft, cancelled, or completed batches in the barcode app.
Original PR description
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which…
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch - Scan anything #### > Traceback #### Other issues: The same flow with a cancelled batch triggers the same tracebacks and, with a done batch triggers the message: "This picking is already done". ### Cause of the issue: Since `this.state.view === "barcodeLines"`, scans are processed as if we were processing an existing `BarcodePickingBatchModel` with lines: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/components/main.js#L204-L209 In particular, if the scan corresponds to a product, and error will be raised because the scan can not process a `createNewLine` for the scanned product in the current view and if the scan does not correspond to anything valid, it will raise an error because `this.picking` is undefined and `this.picking.use_existing_lots` raises an error: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/models/barcode_model.js#L1115 https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L177-L179 opw-5162164 Forward-Port-Of: odoo/enterprise#98022 Forward-Port-Of: odoo/enterprise#97526
A failing test setup was corrected so spreadsheet edition tests pass when that module is installed on its own. This helps keep automated validation reliable and reduces false failures during quality checks.
Original PR description
tests `test_image_attachment_copy_access_rights` and `test_image_attachment_deleted_access_rights` are failing when only `test_spreadsheet_edition` is installed. Runbot error: 233711
Fixed an error that could block French companies from sending a VAT report when launching the EDI VAT action from the tax return report menu. The wizard now keeps the related tax return context, so users can submit the VAT report without encountering a crash.
Original PR description
Steps to reproduce: - With a FR Company Setup - Create a bill with tax in past month - Create Tax return for past month, validate - Click "Submit", fill the required vals in wizard and 'Send VAT report' - Everything works as expected - From Accounting / Accounting / Closing / Tax Returns click Cog > EDI VAT - Fill the required vals in wizard and again 'Send VAT report' Issue: Traceback will raise `ValueError: Expected singleton: account.return()` Analysis: When opening the VAT Return wizard from Accounting / Accounting / Closing / Tax Returns the value of return record is not passed on opw-5107549 Forward-Port-Of: odoo/enterprise#98544
Point-of-sale records created locally are now preserved when syncing with the server, even if the server response does not yet include them. This reduces the risk of losing pending sales, refunds, or settlement information during connectivity or timing issues.
Original PR description
*: l10n_br_edi_pos, pos_settle_due, pos_urban_piper Before this commit, when syncing records from the server, local records that were not yet synced (isSynced=false) could be lost if they were not present in the server response. This could happen for example when a record was created locally and the server response did not include it. This commit fixes this issue by ensuring that local records are always kept when syncing, even if they are not present in the server response. This is done by merging the local records with the server records based on their keys. --- This commit also replace all checks of the form typeof id === "number" with isSynced checks. This is because the id of a record can be a temporary string id before it is synced with the server. Forward-Port-Of: odoo/enterprise#94568
New salary offers created from an existing offer now receive a proper secure link with a generated token. This prevents broken offer links showing "False" instead of a valid token, helping recruiters share salary configurator offers reliably.
Original PR description
_______________________________________ ## Short functional explanation of the error When creating an offer on the page of another offer, the salary configurator url doesn't contain a token, but instead, contains token = false. ## Reproduction Steps 1. Open the recruitment module. If there's no job position nor application, create some. 2. Open an existing application and click on Generate Offer. 3. Click on New on the top left of the screen. 4. Fill the new application and click on save. ### Expected behavior The field 'Link' contains an URL with, at the end, &token=x, with x a randomly generated token. ### Unexpected behavior The field 'Link' contains an URL with, at the end, &token=False. ## Origin of the issue The token generation code wasn't called when creating a new offer the way described in reproduction steps. _________________________________________ opw-4885796 --- Forward-Port-Of: odoo/enterprise#98503 Forward-Port-Of: odoo/enterprise#89546
Belgian accounting now assigns the correct VAT-related receivable and payable accounts to FPS and Collection Center partners. Bank transactions for VAT payments can be matched more automatically, reducing manual reconciliation work and payment-closing errors.
Original PR description
This commit sets AR and AP accounts of "FPS" and "Collection Center" partners with the 2 new added VAT accounts. Additionally, a new reconciliation rules that detects the partner and the communication and creates a counter entry. The partner "FPS" have been added to the VAT closing line for auto-reconciliation with bank transaction. task-5148985
This fix prevents salary rule forms from incorrectly requiring a percentage base field after certain condition changes. Payroll users can now save salary rules without unnecessary validation errors, reducing friction when configuring payroll rules.
Original PR description
**Steps to reproduce:** - Install the hr_payroll module. - Open a salary rule form view. - Change amount_select to Percentage and try to save → validation error occurs because amount_percentage_base is required. - Keep amount_select the same and change condition_select to Salary Input → the same validation error occurs. **Issue:** The amount_percentage_base field is incorrectly made required even when condition_select changes. The requirement should depend solely on amount_select, not condition_select. **Cause:** The field amount_percentage_base remains mandatory when condition_select is updated, leading to validation errors. **Fix:** This PR adjusts the logic so that the amount_percentage_base field is required only when appropriate, based on both condition_select and amount_select. task-5090125 Forward-Port-Of: odoo/enterprise#95419
On very small screens, the empty-list illustration no longer covers the barcode scan button. This ensures warehouse users on handheld scanners or small phones can continue scanning items even when a filtered list has no results.
Original PR description
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra…
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of the screen where the search bar is located (in div .o_control_panel). The issue is that in barcode there is another element where the button to scan is located (o_kanban_tip_filter), and since the image is absolutely positioned relative to the top rather than this element, it ends up overlapping the button and the text, preventing interaction. ### Why the fix: The solution we chose is to change the position of the image to relative, for the image to not hide the text. Another possible solution was to make the image (more specifically .o_view_nocontent .o_nocontent_help) ignore all input, allowing them to go through the image and reach the button below. opw-5123880 Forward-Port-Of: odoo/enterprise#98243
This change fixes an intermittent issue that could occur when closing AI-related chat windows. It makes the close process happen in the expected order, reducing unpredictable failures and improving reliability for users.
Original PR description
Attempt to fix runbot error 233689 by refactoring `_onClose` across patches. The problem occurs because of the async nature and the many side effects that occur. `_onClose` is not supposed to be async. PR community https://github.com/odoo/odoo/pull/233597
Point of Sale cash session names now keep a continuous sequence when cash posting fails. This prevents missing session numbers, making records easier to follow and reducing confusion during audits or daily reconciliation.
Original PR description
Before this commit, if an issue occurred while posting the cash details, the session sequence would still increment even though the operation failed, leading to gaps in session names. With this commit, the sequence only increments when the operation succeeds, ensuring continuous session naming without gaps. related: https://github.com/odoo/odoo/pull/233183 opw-5180712 Forward-Port-Of: odoo/enterprise#98468 Forward-Port-Of: odoo/enterprise#98157
This update makes closing AI-related chat windows more dependable by preventing timing issues that could cause inconsistent behavior. It helps reduce errors in automated checks and improves stability for users interacting with chat features.
Point of Sale preparation displays now include any free-text details entered for custom product attributes. This helps kitchen or preparation staff see the full customer request, matching the information already shown on receipts.
Original PR description
Steps to reproduce: ------------------- 1. Create a PoS product with an attribute of type "Radio", name it "X", and add a value to it, name it "Y", with the "Free text" option selected. 2. From PoS, click the product, for the attribute "X", select the value "Y", and enter some text in the text input area "blabla". 3. Order the product. Observation: On the preparation display, only the attribute name and value are display, but not the entered text, i.e. "X: Y" instead of "X: Y: blabla". Fix: ---- We now show the custom value (free text) if any. This matches what's been shown on the receipt in PoS. opw-5111768 Forward-Port-Of: odoo/enterprise#95874
The salary contract test setup was corrected to rely only on permission groups from modules it already depends on. This prevents avoidable test failures and helps keep quality checks stable without changing employee-facing functionality.
Original PR description
Before this commit: Running `hr_contract_salary` tests were failing, due to groups used from the module `hr_payroll`, which is not part of the dependencies. After this commit: Use groups from the dependencies. runbot-233547 Forward-Port-Of: odoo/enterprise#98286
Code cleanup and technical improvements
The IoT Box now includes its device handlers by default instead of downloading them from the database during startup. This should make startup faster and reduce setup or connection issues for payment terminals, black boxes, cameras, and quality devices.
Original PR description
To speed up the IoT Box startup process and reduce the amount of potential issues, we now avoid downloading handlers from the database by providing them all by default on the IoT Box. odoo/odoo#233991
This update modernizes internal messaging-related code by using the current shared model reference path instead of an older compatibility path. It should not change day-to-day behavior for users, but it helps keep maintenance simpler across AI, approvals, VoIP, live chat helpdesk, and WhatsApp features.
Original PR description
Imports of `@mail/src/model` should be made through `@mail/model/export`. In the past the source code of JS models was also in `@mail/core/common` but was moved in its `model/` folder. `@mail/core/common/record` was kept for backward compatibility.
The appointment calendar was adjusted to stay compatible with recent calendar display changes. This keeps appointment scheduling working smoothly as the interface evolves to support viewing multiple months.
Original PR description
This commit makes some changes to the appointment calendar renderer, since the renderer from /web has been changed to support the display of multiple months at once in the ActionSwiper.
This update cleans and standardizes website-related JavaScript files across several website modules. It helps keep the codebase easier to maintain without introducing expected changes for end users.
Original PR description
[LINT] website_documents, *: lint website related files *: website_enterprise, website_generator, website_product_barcodelookup, website_studio The goal of this commit is to lint the website related js files. task-5110180
20 changes
Enhancements to existing features
Estonian VAT report XML exports now process large batches of accounting entries together instead of recalculating each line separately. This prevents timeouts on high-volume periods and makes monthly VAT filing more reliable for companies with many transactions.
Original PR description
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this…
Behavior before: When exporting the VAT report to XML, each newly added line triggered a fresh _compute_expression_totals_for_each_column_group call. With large volumes of journal items, this resulted in excessive repeated queries and, for big datasets, timeout errors. Behavior after: Introduced _custom_unfold_all_batch_data_generator, which batches the computation of expression totals for all lines. Now, journal items are resolved in bulk and mapped back to their respective moves, significantly reducing redundant queries. The VAT XML export completes successfully, even on months with very large datasets. Root cause: The Estonia VAT report was missing a batch unfold method (_custom_unfold_all_batch_data_generator). Without it, the system executed totals computation for each line individually instead of in batch, causing major performance degradation. Benchmark: | Period size (journal items) | Before patch | After patch | |----------------------------------------|----------------------|--------------------| | ~15k | 7s | 5s | | ~200k+ | Timeout error| 21s | opw-5046077 Forward-Port-Of: odoo/enterprise#97660 Forward-Port-Of: odoo/enterprise#95047
[task-5207451](https://www.odoo.com/odoo/all-tasks/5207451)
Original PR description
[task-5207451](https://www.odoo.com/odoo/all-tasks/5207451)
task-5207451
Original PR description
task-5207451
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Fixes an issue where changing quantities for multiple combo products in an unsaved sales order could move the related combo items into the wrong position. This helps sales users keep orders clear and accurate while editing, reducing the risk of confusing or incorrect order lines.
Original PR description
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving,…
Steps to Reproduce: - Create a Sale Order containing two combo products placed consecutively. - Change the quantity of the first combo → corresponding combo items update correctly. - Without saving, change the quantity of the second combo. - Observe that the combo items now appear misplaced — items from the second combo are inserted before those of the first combo. Issue: - The order of combo items becomes incorrect when multiple combo products are updated consecutively in the same unsaved Sale Order. Cause: - During `onchange`, the `self.order_line` recordset reflects the *in-memory order of applied commands* rather than the database `sequence` field because they are not saved in the DB during the edition. - Each `onchange` rebuilds `order_line` using concatenated command lists (`delete + create + update`), So when multiple combos are modified without save, newly created combo items are appended according to command evaluation order — not by logical grouping. - This causes combo items to shift relative to their parent combo lines. Solution: - Restrict the recomputation of order lines to non-combo lines by filtering out combo item lines during the rebuild. As combo items will always be in their desired sequence. - This ensures that combo items always stay under their respective parent combos and their sequence is preserved, regardless of the order in which combos are updated. opw-5148770 Affected Version:18.0 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233740
This fixes an issue in the website editor where undoing a change could restore text or elements in the wrong order in some browsers. Users can now rely on history revert actions to preserve the intended content layout, reducing editing confusion and accidental formatting errors.
Original PR description
Problem: Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`). Cause: In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the…
Problem:
Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`).
Cause:
In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the referenced sibling was connected to the live DOM (`.isConnected`).
When that check failed, the fallback was `parent.append()`. On some Firefox versions, mutation events list the parent removal *after* its children’s, meaning the parent is reinserted first while the children’s siblings still exist but are detached. Because `.isConnected` returned false, the fallback `append()` misplaced nodes and broke the order.
Example (processed in reverse order):
```js
[
{ type: 'remove', id: 'p', parentId: 'root', node: { tagName: 'P' } },
{ type: 'remove', id: 'b1', parentId: 'p', nextId: 'b2',
node: { textValue: 'b' } },
{ type: 'add', id: 'b1', append: 'x', node: { textValue: 'b' } },
{ type: 'remove', id: 'c1', parentId: 'p', node: { textValue: 'c' } },
{ type: 'add', id: 'c1', append: 'x', node: { textValue: 'c' } },
]
```
During revert:
- Child removals (b1, c1) are processed first.
- Their sibling nodes exist but are detached → .isConnected false.
- Fallback append() used → "b" inserted after "c" → acb.
- `<p>` restored last with children in wrong order.
Solution:
Remove the `.isConnected` condition.
`before()` and `after()` work even on detached nodes, preserving the original child order regardless of browser mutation sequence.
Steps to reproduce:
- Open todo.
- Have this:
```html
<p>a[]</p>
<p>b<br>c</p>
```
- Press Delete.
- Observe "b" and "c" are not in the right order.
opw-5139795
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#233582The Cambodian localization package now avoids duplicate tax names that could block manual chart template installation. This helps businesses set up Cambodian accounting correctly without installation errors.
Original PR description
Fixes an issue where some taxes in the Cambodian package have the same name, leading to errors when manually installing the chart template. Interestingly enough, the constraints does not trigger on the demo data company. Task [link](https://www.odoo.com/odoo/project.task/5194444) task-5194444 Forward-Port-Of: odoo/odoo#233066 Forward-Port-Of: odoo/odoo#232968
This update fixes an internal automated test for the website editor so it waits for each step before continuing. It helps avoid false failures during busy test runs, improving release confidence without changing user-facing behavior.
Original PR description
This test was not awaiting each step properly, which becomes visible when the runbot is overloaded and the querySelector calls return null, at which point accessing `click` or `value` would trigger a traceback. runbot-161423 Forward-Port-Of: odoo/odoo#233900
Calendar events created through appointments now use the intended contact instead of guessing from the attendee list. This prevents incorrect contact information from appearing and makes related automated checks more stable.
Original PR description
When a calendar event is created, the system automatically adds contact details to the description. It currently "guesses" this contact by picking the first attendee who isn't the organizer. This guessing logic can be wrong, especially for events created by other apps (like Appointments) where a specific contact (e.g., the booker) is known. This not only shows the wrong information to the user but also causes instability in automated tests, which can fail unpredictably depending on the order of attendees. This commit refactors the event creation logic to be more flexible. It allows other modules to specify *which* partner should be used as the main contact, rather than leaving it to a guess. This makes the feature more robust and stabilizes the tests that rely on this behavior. Task-5207757
Calendar events now use the correct known contact when adding details to event descriptions instead of guessing from the attendee list. This prevents incorrect contact information from appearing and makes related appointment and calendar behavior more predictable.
Original PR description
When a calendar event is created, the system automatically adds contact details to the description. It currently "guesses" this contact by picking the first attendee who isn't the organizer. This guessing logic can be wrong, especially for events created by other apps (like Appointments) where a specific contact (e.g., the booker) is known. This not only shows the wrong information to the user but also causes instability in automated tests, which can fail unpredictably depending on the order of attendees. This commit refactors the event creation logic to be more flexible. It allows other modules to specify *which* partner should be used as the main contact, rather than leaving it to a guess. This makes the feature more robust and stabilizes the tests that rely on this behavior. Task-5207757
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch
Original PR description
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which…
### Issue: Scans processed during picking batch creation in the barcode app are interpreted as scans related to the BarcodePickingBatchModel edition (that is product, lot, package,... scans) which does not make sense and raises multiple errors. ### Steps to reproduce: - In the settings enable "Batch Transfers" - Inventory/Operations/Transfers/Batch Transfers - Create a new batch and do not confirm it - Go to the barcode app > Batch Transfers > Clear filters - Select your draft batch - Scan anything #### > Traceback #### Other issues: The same flow with a cancelled batch triggers the same tracebacks and, with a done batch triggers the message: "This picking is already done". ### Cause of the issue: Since `this.state.view === "barcodeLines"`, scans are processed as if we were processing an existing `BarcodePickingBatchModel` with lines: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/components/main.js#L204-L209 In particular, if the scan corresponds to a product, and error will be raised because the scan can not process a `createNewLine` for the scanned product in the current view and if the scan does not correspond to anything valid, it will raise an error because `this.picking` is undefined and `this.picking.use_existing_lots` raises an error: https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode/static/src/models/barcode_model.js#L1115 https://github.com/odoo/enterprise/blob/ce7460b27028d4133c4689afd2e8f303268494a0/stock_barcode_picking_batch/static/src/models/barcode_picking_batch_model.js#L177-L179 opw-5162164 Forward-Port-Of: odoo/enterprise#98022 Forward-Port-Of: odoo/enterprise#97526
_______________________________________ ## Short functional explanation of the error When creating an offer on the page of another offer, the salary configurator url doesn't contain a token, but instead, contains token = false. ## Reproduction Steps 1. Open the recruitment module. If there's no job position nor application, create some. 2. Open an existing application and click on Generate Offer. 3. Click on New on the top left of the screen. 4. Fill the new application and click on sav
Original PR description
_______________________________________ ## Short functional explanation of the error When creating an offer on the page of another offer, the salary configurator url doesn't contain a token, but instead, contains token = false. ## Reproduction Steps 1. Open the recruitment module. If there's no job position nor application, create some. 2. Open an existing application and click on Generate Offer. 3. Click on New on the top left of the screen. 4. Fill the new application and click on save. ### Expected behavior The field 'Link' contains an URL with, at the end, &token=x, with x a randomly generated token. ### Unexpected behavior The field 'Link' contains an URL with, at the end, &token=False. ## Origin of the issue The token generation code wasn't called when creating a new offer the way described in reproduction steps. _________________________________________ opw-4885796 --- Forward-Port-Of: odoo/enterprise#98503 Forward-Port-Of: odoo/enterprise#89546
**Steps to reproduce:** 1. Install the module `project_timesheet_forecast_sale`. 2. Go to Project > Configuration > Projects and open any project. 3. Go to Dashboard, click the "Timesheets and Planning" button. **Issue:** - Opening the "Timesheets and Planning" view raised the following error: `TypeError: Cannot read properties of undefined (reading 'length')` **Cause:** - Error caused by [method](https://github.com/odoo/odoo/blob/5be6ef1ae3958a25e680f5fa30824fec57d63efe/addons/
Original PR description
**Steps to reproduce:** 1. Install the module `project_timesheet_forecast_sale`. 2. Go to Project > Configuration > Projects and open any project. 3. Go to Dashboard, click the "Timesheets and…
**Steps to reproduce:**
1. Install the module `project_timesheet_forecast_sale`.
2. Go to Project > Configuration > Projects and open any project.
3. Go to Dashboard, click the "Timesheets and Planning" button.
**Issue:**
- Opening the "Timesheets and Planning" view raised the following error:
`TypeError: Cannot read properties of undefined (reading 'length')`
**Cause:**
- Error caused by [method](https://github.com/odoo/odoo/blob/5be6ef1ae3958a25e680f5fa30824fec57d63efe/addons/web/static/src/views/pivot/pivot_renderer.js#L107-L109), occurred because the `planned_costs` and `effective_costs` fields are float fields but were declared with `widget="monetary"` in the pivot view. Since these fields use `format_type="monetary"` and have no corresponding `currency_field`, the pivot renderer failed to resolve currency mappings (`currency_ids` was undefined) and crashed.
**Solution:**
- Removed the `widget="monetary"` attribute from the `planned_costs` and `effective_costs` fields in the pivot view so they are treated as numeric measures instead of monetary ones.
**opw-5179265****Steps to reproduce:** 1. Install the module `project_timesheet_forecast_sale`. 2. Go to Project > Configuration > Projects and open any project. 3. On the project's dashboard, click the Dashboard stat button. 4. In the stats dialog, click "Timesheets and Planning". **Issue:** - Opening the Timesheets and Planning stat button from a Project dashboard (after installing `project_timesheet_forecast_sale`) raises the following error: TypeError: Cannot read properties of undefined (re
Original PR description
**Steps to reproduce:** 1. Install the module `project_timesheet_forecast_sale`. 2. Go to Project > Configuration > Projects and open any project. 3. On the project's dashboard, click the Dashboard…
**Steps to reproduce:**
1. Install the module `project_timesheet_forecast_sale`.
2. Go to Project > Configuration > Projects and open any project.
3. On the project's dashboard, click the Dashboard stat button.
4. In the stats dialog, click "Timesheets and Planning".
**Issue:**
- Opening the Timesheets and Planning stat button from a Project dashboard (after installing `project_timesheet_forecast_sale`) raises the following error:
TypeError: Cannot read properties of undefined (reading 'length')
**Cause:**
- The method _getCellCurrency() expected every dataset to have corresponding currencyIds, but the Timesheet/Forecast report does not include any currency information in its configuration data.
As a result, config.data.currencyIds[key] was empty, leading to the crash when trying to access .length.
**Solution:**
- Handle missing currencyIds in _getCellCurrency() by checking for an empty or undefined entry before accessing it.
If no currency is defined (as is the case for timesheet/forecast reports), the method now simply returns.
**opw-5179265**Before this commit, if an issue occurred while posting the cash details, the session sequence would still increment even though the operation failed, leading to gaps in session names. With this commit, the sequence only increments when the operation succeeds, ensuring continuous session naming without gaps. related: https://github.com/odoo/enterprise/pull/98157 opw-5180712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit, if an issue occurred while posting the cash details, the session sequence would still increment even though the operation failed, leading to gaps in session names. With this commit, the sequence only increments when the operation succeeds, ensuring continuous session naming without gaps. related: https://github.com/odoo/enterprise/pull/98157 opw-5180712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233997 Forward-Port-Of: odoo/odoo#233183
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of
Original PR description
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra…
On small screens (e.g., Zebra scanner, iPhone 4), the image overlaps the barcode scan button, making it impossible to click and scan new items. ### Steps to reproduce: On a small screen size (Zebra scanner, Iphone 4,..) * Open barcode app * Go on Operations -> Receipts * Apply a filter so that the list becomes empty. -> the image is over the barcode button and the text. ### Observation: Our image (in div .o_view_nocontent) has position absolute, anchoring it to the top part of the screen where the search bar is located (in div .o_control_panel). The issue is that in barcode there is another element where the button to scan is located (o_kanban_tip_filter), and since the image is absolutely positioned relative to the top rather than this element, it ends up overlapping the button and the text, preventing interaction. ### Why the fix: The solution we chose is to change the position of the image to relative, for the image to not hide the text. Another possible solution was to make the image (more specifically .o_view_nocontent .o_nocontent_help) ignore all input, allowing them to go through the image and reach the button below. opw-5123880 Forward-Port-Of: odoo/enterprise#98243
Before this commit, if an issue occurred while posting the cash details, the session sequence would still increment even though the operation failed, leading to gaps in session names. With this commit, the sequence only increments when the operation succeeds, ensuring continuous session naming without gaps. related: https://github.com/odoo/odoo/pull/233183 opw-5180712 Forward-Port-Of: odoo/enterprise#98468 Forward-Port-Of: odoo/enterprise#98157
Original PR description
Before this commit, if an issue occurred while posting the cash details, the session sequence would still increment even though the operation failed, leading to gaps in session names. With this commit, the sequence only increments when the operation succeeds, ensuring continuous session naming without gaps. related: https://github.com/odoo/odoo/pull/233183 opw-5180712 Forward-Port-Of: odoo/enterprise#98468 Forward-Port-Of: odoo/enterprise#98157
The employee form view displayed misaligned or inconsistent avatar images on mobile screens. task-5058793 Forward-Port-Of: odoo/odoo#225157
Original PR description
The employee form view displayed misaligned or inconsistent avatar images on mobile screens. task-5058793 Forward-Port-Of: odoo/odoo#225157
Steps to reproduce: ------------------- 1. Create a PoS product with an attribute of type "Radio", name it "X", and add a value to it, name it "Y", with the "Free text" option selected. 2. From PoS, click the product, for the attribute "X", select the value "Y", and enter some text in the text input area "blabla". 3. Order the product. Observation: On the preparation display, only the attribute name and value are display, but not the entered text, i.e. "X: Y" instead of "X: Y: blabla".
Original PR description
Steps to reproduce: ------------------- 1. Create a PoS product with an attribute of type "Radio", name it "X", and add a value to it, name it "Y", with the "Free text" option selected. 2. From PoS, click the product, for the attribute "X", select the value "Y", and enter some text in the text input area "blabla". 3. Order the product. Observation: On the preparation display, only the attribute name and value are display, but not the entered text, i.e. "X: Y" instead of "X: Y: blabla". Fix: ---- We now show the custom value (free text) if any. This matches what's been shown on the receipt in PoS. opw-5111768 Forward-Port-Of: odoo/enterprise#95874
Hr Payroll users that are meant to be able to use the Resend Payslip by email button do not have enough access right to get the documents token to put into the email "Your Payslip" button. Add a sudo on the payslip to get the document access url after the check of user role has been done. If have the right to use the button, sudo the rest. Task-5049444 Forward-Port-Of: odoo/enterprise#93420
Original PR description
Hr Payroll users that are meant to be able to use the Resend Payslip by email button do not have enough access right to get the documents token to put into the email "Your Payslip" button. Add a sudo on the payslip to get the document access url after the check of user role has been done. If have the right to use the button, sudo the rest. Task-5049444 Forward-Port-Of: odoo/enterprise#93420
12 changes
Enhancements to existing features
Users who are already registered as Peppol receivers in another Odoo database no longer need to manually deregister and start over. Odoo now detects the existing registration and sends a secure email link so they can transfer the Peppol connection to the current database more smoothly.
Original PR description
### Summary Previously, when a user attempted to **register as a Peppol receiver** while already registered through a different Odoo database, the system would raise a **User Error**. The user had to…
### Summary
Previously, when a user attempted to **register as a Peppol receiver** while already registered through a different Odoo database, the system would raise a **User Error**.
The user had to **manually deregister** and **re-register** from the desired database.
---
### New Behavior (After This Commit)
With this update:
- The system **detects existing Peppol registrations** across databases.
- Instead of raising an error, it now **sends an automated email** to the user with a **secure transfer link**.
- This allows the user to **migrate their Peppol connection** to the current database seamlessly.
---
### Flow Overview
```text
┌────────────────────────────┐
│ User initiates Peppol │
│ registration (becomes │
│ sender) │
└────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Check existing registration │
└────────────┬─────────────────┘
│
┌──────────────┴──────────────┐
▼ ▼
┌─────────────────────┐ ┌──────────────────────────────┐
│ User NOT registered │ │ User ALREADY registered |
│ in any Odoo DB │
└────────────┬────────┘ └──────────────┬───────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────────┐
│ Proceed with normal │ │ Send email with transfer link│
│ registration flow │ │ to the user │
└──────────────────────────┘ └──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ User clicks transfer link
│
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Peppol connection migrated
└──────────────────────────────┘
```
---
iap pr- https://github.com/odoo/iap-apps/pull/1236
task- 5023252Resolved issues and error corrections
This fix ensures website building snippets appear correctly when using Arabic or other right-to-left languages. It helps users edit website pages without missing content options due to layout positioning issues.
Original PR description
Steps to reproduce: =================== - Set arabic as default language for website - Try to add a snippet -> you can't see the snippets Cause: ====== Snippets were fetched correctly but were not visible. In RTL languages (like Arabic), the CSS `transform-origin` was set to 'top right', rendering the snippets off-screen. This is due to the browser's interpretation of positioning in RTL mode. For more details, see MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/ Properties/position Solution: ========= Force the snippet preview's position by setting `left: 0`. This ensures its positioning is always aligned to the left, regardless of the `transform-origin` value dynamically set by the browser in RTL mode. opw-5214703
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main product image is not removed as expected after the tour completes. Cause ----- Both tours assume that once the product `<img>` element is removed from the DOM, the action is fully completed. The tour then ends, and the remaining Python code verifies the result. However, this assumption can l
Original PR description
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main…
Versions -------- 18.0+ Issue ----- The `test_website_sale_add_and_remove_main_product_image_no_variant` and `test_website_sale_remove_main_product_image_with_variant` tours fail because the main product image is not removed as expected after the tour completes. Cause ----- Both tours assume that once the product `<img>` element is removed from the DOM, the action is fully completed. The tour then ends, and the remaining Python code verifies the result. However, this assumption can lead to issues. If the save request takes longer than expected, the Python code may execute prematurely and fail. Solution -------- Add a step at the end of both tours to wait for the `<img>` element to be fully saved and updated in the preview DOM. Additionally, during debugging, it was observed that using an alias URL (i.e., a redirect) to an `ir.attachment` could introduce further issues or slow down the test due to the server fetching the image with a remote call. To address this, this commit replaces the alias URL with a simple binary attachment. opw-5159593 runbot-163025 runbot-163615
**PROBLEM** Internal users can access the documents of a private project even when they are not followers of the project. They shouldn't. **STEP TO REPRODUCE** 1. Create a project, and set its visibility to Invited internal users (private), and upload a document to the project folder. 2. Switch to a user that is not a follower of the project, but is a user of the document app. 3. Go to the documents app, and notice you have access to files in the private project folder. **CAUSE** 1. W
Original PR description
**PROBLEM** Internal users can access the documents of a private project even when they are not followers of the project. They shouldn't. **STEP TO REPRODUCE** 1. Create a project, and set its…
**PROBLEM**
Internal users can access the documents of a private project even when they are not followers of the project. They shouldn't.
**STEP TO REPRODUCE**
1. Create a project, and set its visibility to Invited internal users (private), and upload a document to the project folder.
2. Switch to a user that is not a follower of the project, but is a user of the document app.
3. Go to the documents app, and notice you have access to files in the private project folder.
**CAUSE**
1. When creating the project folder, we don't specify `access_ids`, which means it will copy the `access_ids` of the folder above it. If a user have access to the "Project" folder, they will have access to any sub-folder ("Project" folder is the default parent folder of the any project folder).
2. `is_access_via_link_hidden` is by default set to False, which means the project folder is visible to anyone who has access to its parent folder.
**FIX**
1. Don't copy `access_ids` from the parent folder.
2. If project visibility is private, `is_access_via_link_hidden` is set to True.
3. To give access to the folder to the followers of the project, update the `access_ids` of the project folder and documents when add/removing followers.
opw-4791346Problem: Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`). Cause: In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the referenced sibling was connected to the live DOM (`.isConnected`). When that check failed, the fallback was `parent.append()`. On some Firefox versions, mutation events list the parent removal *after* its children’s, meaning the parent is reinserted first while the children’s siblings still exist b
Original PR description
Problem: Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`). Cause: In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the…
Problem:
Reverting history sometimes restores children in the wrong order (e.g. `acb` instead of `abc`).
Cause:
In `historyRevert`, node reinsertion relied on `nextId` / `previousId` only if the referenced sibling was connected to the live DOM (`.isConnected`).
When that check failed, the fallback was `parent.append()`. On some Firefox versions, mutation events list the parent removal *after* its children’s, meaning the parent is reinserted first while the children’s siblings still exist but are detached. Because `.isConnected` returned false, the fallback `append()` misplaced nodes and broke the order.
Example (processed in reverse order):
```js
[
{ type: 'remove', id: 'p', parentId: 'root', node: { tagName: 'P' } },
{ type: 'remove', id: 'b1', parentId: 'p', nextId: 'b2',
node: { textValue: 'b' } },
{ type: 'add', id: 'b1', append: 'x', node: { textValue: 'b' } },
{ type: 'remove', id: 'c1', parentId: 'p', node: { textValue: 'c' } },
{ type: 'add', id: 'c1', append: 'x', node: { textValue: 'c' } },
]
```
During revert:
- Child removals (b1, c1) are processed first.
- Their sibling nodes exist but are detached → .isConnected false.
- Fallback append() used → "b" inserted after "c" → acb.
- `<p>` restored last with children in wrong order.
Solution:
Remove the `.isConnected` condition.
`before()` and `after()` work even on detached nodes, preserving the original child order regardless of browser mutation sequence.
Steps to reproduce:
- Open todo.
- Have this:
```html
<p>a[]</p>
<p>b<br>c</p>
```
- Press Delete.
- Observe "b" and "c" are not in the right order.
opw-5139795
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#233582**Steps to reproduce** 1. Create a subscription SO with both a recurring and a non-recurring line. 2. Add a discount to the non-recurring line. 3. Confirm the SO. 4. Change the "Start date" of the SO. Issue: the discount on the non-recurring line has been removed. **Solution** Remove the order's start date from the dependencies and manually call `_compute_discount` when needed (for upsell sub lines). opw-4822617
Original PR description
**Steps to reproduce** 1. Create a subscription SO with both a recurring and a non-recurring line. 2. Add a discount to the non-recurring line. 3. Confirm the SO. 4. Change the "Start date" of the SO. Issue: the discount on the non-recurring line has been removed. **Solution** Remove the order's start date from the dependencies and manually call `_compute_discount` when needed (for upsell sub lines). opw-4822617
This test was not awaiting each step properly, which becomes visible when the runbot is overloaded and the querySelector calls return null, at which point accessing `click` or `value` would trigger a traceback. runbot-161423 Forward-Port-Of: odoo/odoo#233900
Original PR description
This test was not awaiting each step properly, which becomes visible when the runbot is overloaded and the querySelector calls return null, at which point accessing `click` or `value` would trigger a traceback. runbot-161423 Forward-Port-Of: odoo/odoo#233900
Issue ----- Removing a line using the subcontracting wizard does not delete the line in DB, there is a "phantom" ML. Steps to reproduce ----- - Create a subcontracted product with 2 components - Add one of each component in subcontractor's stock - Create a PO for the finished product and confirm it - Go to the production - Open the "Record components" wizard - Set quantity then remove the second line - Confirm production (don't update consumption) - Go to Inventory > Reporting > Mo
Original PR description
Issue ----- Removing a line using the subcontracting wizard does not delete the line in DB, there is a "phantom" ML. Steps to reproduce ----- - Create a subcontracted product with 2 components - Add…
Issue ----- Removing a line using the subcontracting wizard does not delete the line in DB, there is a "phantom" ML. Steps to reproduce ----- - Create a subcontracted product with 2 components - Add one of each component in subcontractor's stock - Create a PO for the finished product and confirm it - Go to the production - Open the "Record components" wizard - Set quantity then remove the second line - Confirm production (don't update consumption) - Go to Inventory > Reporting > Moves History and remove the "Done" filter > There is a pending move in the report Cause ----- When saving the wizard's changes, we call a write on the production's `move_line_raw_ids` field to remove delete the line. The field is a simple compute, so we go through its' inverse method https://github.com/odoo/odoo/blob/be3a4283c383d187570f5a73f337030e6ae9d05c/addons/mrp_subcontracting/models/mrp_production.py#L34-L46 The problem is that we populate `line_by_product` using the values present in `move_line_raw_ids` from which we just removed the line. This means that when we do `move.move_line_ids = line_by_product.pop(move.product_id, self.env['stock.move.line'])` we replace the value of `move_line_ids` with only the remaining ones, which means we unlink the move line (*from the move*). Because the inverse field (`move_id` of the SML) is not set as `ondelete='cascade'`, the link is broken but the line remains in db. https://github.com/odoo/odoo/blob/f173c738b1adcf85a80eb641ad307b7cccf17294/odoo/fields.py#L4311-L4322 We cannot change the field to `ondelete='cascade'` as such a change would not be stable. Solution ----- Keep reference of the lines to be removed in order to delete them once `move_line_ids` has been updated. ----- Ticket: opw-4817397 Forward-Port-Of: odoo/odoo#229310
Community PR: https://github.com/odoo/odoo/pull/233842 Forward-Port-Of: odoo/enterprise#98492
Original PR description
Community PR: https://github.com/odoo/odoo/pull/233842 Forward-Port-Of: odoo/enterprise#98492
Repro: - Create DDM for a client - Create 4+ invoices for him - Pay with SEPA - Go to batch payment set it with SEPA - Add all the invoices and set the date to any date <5 days from today. - A yellow line will appear along with (View All).. / click it - From the view click on any payment. - Exception arises saying made_sequence_gap not found in account.payment Issue: made_sequence_gap belongs to 'account.move' incompatible with 'account.payment' causing the exception. Solution:
Original PR description
Repro: - Create DDM for a client - Create 4+ invoices for him - Pay with SEPA - Go to batch payment set it with SEPA - Add all the invoices and set the date to any date <5 days from today. - A yellow line will appear along with (View All).. / click it - From the view click on any payment. - Exception arises saying made_sequence_gap not found in account.payment Issue: made_sequence_gap belongs to 'account.move' incompatible with 'account.payment' causing the exception. Solution: Here the view_duplicated_moves_tree_js view is intended for account.move elements not for account.payment ones, So I included it only when the resModel is account.move. opw-5149260
Enterprise PR: https://github.com/odoo/enterprise/pull/98492 Forward-Port-Of: odoo/odoo#233842
Original PR description
Enterprise PR: https://github.com/odoo/enterprise/pull/98492 Forward-Port-Of: odoo/odoo#233842
This update fixes the way Chilean state names are displayed in customer addresses. It replaces placeholder numeric codes with the official country-standard codes, helping ensure addresses are accurate and consistent for users and integrations.
Original PR description
**Steps to reproduce:** 1. Go to Sales > Create and edit a new customer. 2. Select Chile as the country and choose a state. **Issue:** - State codes appear as numbers (e.g., 01, 02, 03...) which are not ISO-compliant. **Cause**: - State codes in the CSV file were defined as simple numbers instead of proper ISO codes. <img width="601" height="146" alt="image" src="https://github.com/user-attachments/assets/a941c200-467b-4ad5-8f79-ca9e8a92d7b4" /> <img width="443" height="131" alt="image" src="https://github.com/user-attachments/assets/dc1df1b0-2267-499f-ad1d-bb5c9381cd66" /> **Solution**: - Updated all state codes to match the official ISO 3166-2:IQ codes (Reference: https://www.iso.org/obp/ui/#iso:code:3166:CL) **opw-5148562**
2 changes
Resolved issues and error corrections
**Current behavior before PR:** - When a table was created inside another table, resizing the inner table could cause it to overflow its parent cell, making it uneditable. **Desired behavior after PR is merged:** - The inner table no longer overflows its parent cell when resized, ensuring it remains editable. task-5216916
Original PR description
**Current behavior before PR:** - When a table was created inside another table, resizing the inner table could cause it to overflow its parent cell, making it uneditable. **Desired behavior after PR is merged:** - The inner table no longer overflows its parent cell when resized, ensuring it remains editable. task-5216916
Issue ----- When providing multiple SN on the reception form, only the first one is used for the original production, the backorders SN are instead automatically generated. Steps to reproduce ----- - Create a subcontracted produt tracked by serial number - Create a purchase for 2 units of the subcontracted product & confirm - Open reception and create 2 SNs for the product & save the form > Only the first SN is used, the second got replaced by a generated one Cause ----- When sa
Original PR description
Issue ----- When providing multiple SN on the reception form, only the first one is used for the original production, the backorders SN are instead automatically generated. Steps to reproduce ----- -…
Issue ----- When providing multiple SN on the reception form, only the first one is used for the original production, the backorders SN are instead automatically generated. Steps to reproduce ----- - Create a subcontracted produt tracked by serial number - Create a purchase for 2 units of the subcontracted product & confirm - Open reception and create 2 SNs for the product & save the form > Only the first SN is used, the second got replaced by a generated one Cause ----- When saving the form, we write on both the SM's `quantity` and `lot_ids`. This triggers the inverse `set_lot_ids` which updates the SMLs accordingly https://github.com/odoo/odoo/blob/66ad67dfffbd2796f3115ddf9c0aa71d3f0d3c7e/addons/stock/models/stock_move.py#L560 But after `lot_ids` inverse, we trigger the `quantity` one, which calls the move's `_auto_record_components` https://github.com/odoo/odoo/blob/66ad67dfffbd2796f3115ddf9c0aa71d3f0d3c7e/addons/mrp_subcontracting/models/stock_move.py#L85 where we split the production. https://github.com/odoo/odoo/blob/66ad67dfffbd2796f3115ddf9c0aa71d3f0d3c7e/addons/mrp_subcontracting/models/stock_move.py#L97-L101 The production is split into N productions for a single unit of the product (because the `lot_producing_id` field of the MO is a many2one, see https://github.com/odoo/odoo/blob/66ad67dfffbd2796f3115ddf9c0aa71d3f0d3c7e/addons/mrp/models/mrp_production.py#L78-L80 Once the production has been split, a `lot_producing_id` is assigned to the backorder productions by calling `action_generate_serial`. https://github.com/odoo/odoo/blob/66ad67dfffbd2796f3115ddf9c0aa71d3f0d3c7e/addons/mrp_subcontracting/models/stock_move.py#L103-L106 We could instead assign the unused ids in the SM's `lot_ids` to the backorder productions. ----- Ticket: opw-5003930