Daily updates from Odoo
Thursday, June 25, 2026
202 changes
21 changes
Resolved issues and error corrections
This change removes an unnecessary price check from the Peru POS refund test tour. It matters because the tour could fail when the POS configuration currency differed from the company currency, even though the price was not relevant to the workflow being tested.
Original PR description
Before this commit, the tour was checking the price of an article which was not the good one since the currency of the config was not the same as the company one. This commit removes the check of the price which is not even relevant for the tour.
The self-invoicing URL shown on point-of-sale receipts is now generated correctly instead of appearing as an invalid link. This helps customers access their invoice request page without confusion or extra support.
Original PR description
Before this commit: ------------------------- - The self-invoicing URL on the receipt was displayed as `undefined/pos/ticket`. After this commit: ------------------------- - The self-invoicing URL is now generated correctly and displayed properly on the receipt. Task-6271261 Forward-Port-Of: odoo/odoo#271762 Forward-Port-Of: odoo/odoo#270052
This change fixes a problem where importing certain valid UBL invoices could fail if a line had no quantity and no value. Those empty lines are now safely skipped, so the invoice import completes without showing an error message.
Original PR description
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an…
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an import error Such lines are valid UBL but carry no meaningful value, so they are silently skipped after the fix ### Cause: After this commit: https://github.com/odoo/odoo/commit/a7f77f3cfc42764328e7da73a60df8d4cafc968f The `line_extension_amount` was able to go in new parts of the code with a 0.0 value When `line_extension_amount` is set and `invoiced_quantity` is 0, `quantity` is computed as `subtotal * price_quantity / (...)` which resolves to 0 since `subtotal` is also 0 `price_unit = subtotal / quantity` then divides by zero ### Steps to reproduce: - Install `l10n_be` - Import a UBL invoice with a line where `LineExtensionAmount=0`, `InvoicedQuantity=0` and `PriceAmount` is non-zero (You can use the xml on the ticket) Before the fix, the import failed with an error in the chatter opw-6234453 Forward-Port-Of: odoo/odoo#271001
This update corrects how manufacturing work orders are scheduled when several tasks share the same upstream blocker. It now keeps already planned work orders in place, preventing later planning steps from rearranging them in a way that could violate dependencies.
Original PR description
Bug introduced in: https://github.com/odoo/odoo/commit/cfc5c998035b4268c36f5097782888e18e21b4fe Steps to reproduce the bug: - Create a product with a BoM with operation dependencies enabled - Add 4…
Bug introduced in: https://github.com/odoo/odoo/commit/cfc5c998035b4268c36f5097782888e18e21b4fe
Steps to reproduce the bug:
- Create a product with a BoM with operation dependencies enabled
- Add 4 operations on the same workcenter:
- opA: no blocker
- opB: blocked by opA
- opC: blocked by opA
- opD: blocked by opC
- Confirm a manufacturing order from this BoM
- Click Plan
Problem:
opA was scheduled after opB, violating the dependency.
`_plan_workorders` starts planning from the "leaf" workorders (those with no dependents). Given the structure above, the initial set is [opB, opD]. Processing opB first correctly plans opA then opB. But processing opD triggers a recursive chain opD→opC→opA which calls `action_unplan(opA)` and replans it from scratch. By then, opB already occupies the workcenter slot that opA originally held, so opA ends up scheduled after opB.
Solution:
Add `and not wo.is_planned` to the filter on `blocked_by_workorder_ids` in the recursive call inside `_plan_workorders`. Workorders that are already planned are skipped instead of being unplanned and replanned, preserving the correct order.
opw-6299179
Forward-Port-Of: odoo/odoo#271565This update resolves several problems affecting Cashmatic payment certification in Point of Sale. It prevents payment tokens from expiring during long checkout sessions, improves error handling when cash cannot be returned, and avoids delays when the device is unreachable.
Original PR description
First issue: While paying if a user takes more than 15min the token is revoked. Second issue: When cancelling a payment where a user has already inserted money and there is an issue with giving back the money, no popup was shown on the PoS. Third issue: Fetch took too long when the device was not reacheable. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268296
The executive summary now counts the start and end dates as part of the reporting period, instead of leaving out one day. This corrects date-based figures such as Average Debtor Days so report results match the actual calendar span.
Original PR description
`_report_custom_engine_executive_summary_ndays` returned `date_to - date_from`, which is the gap between the two dates, not the count of days they span. For example April 2026-04-01 to 2026-04-30 will returned 29 instead of 30, making Average Debtor Days incorrect. Add +1 so the day count is inclusive of both endpoints, matching the rest of the report's date handling. opw-6215362 Forward-Port-Of: odoo/enterprise#119346 Forward-Port-Of: odoo/enterprise#118953
This change makes a website test tour wait for the correct element before starting a drag-and-drop action. It prevents occasional test failures caused by the tour acting on the wrong target, improving reliability of website testing.
Original PR description
The tour `conditional_visibility_4` has non-deterministic failure, that appears to be caused by the `drag_and_drop` step dragging the element that was the target before the click of the previous step. This commit adds a step to ensure the target is the expected element before the "drag" step starts. runbot-242425 Forward-Port-Of: odoo/odoo#271760
This change prevents the web editor from failing when it processes extremely large documents. It improves reliability and response time by avoiding a browser limit that could otherwise make the page unresponsive.
Original PR description
For complex content, descendants(root) can return more than 100K elements. Using the spread operator expands all descendants into individual function arguments, which may exceed the JavaScript's argument limit and trigger a "Maximum call stack size exceeded" error. Replace with push() each node to the targetNodes. ||Before|After| |-|-|-| |getTargetNodes|Page Unresponsive|585 ms| Related ticket: opw-6303814 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271250
When users quickly save a new calendar event, the title they typed is now preserved instead of sometimes being replaced by the default “no title” label. This prevents confusing event entries and ensures the saved calendar information matches what the user entered.
Original PR description
When creating an event using the quick create form from the calendar view if the user saves the record while the title is still being edited (using alt+c) the record will be saved with the default title: "(no title)" The code currently relies on the record data being up to date by the time onRecordSave is reached. However in the case of a text field, it is only saved when blurred. While there is a mechanism to blur the field when saving using a hotkey, it is completely asynchronous from the save logic of the form. To ensure all fields have comitted their data at save time, the framework has a mechanism to "request changes" which notifies all fields to update the record with their latest value and waits for them to do so. We can simply reuse this mechanism to ensure the data is up to date at recordSave time already, as we don't expect fields to have any changes after it. task-6321702 Forward-Port-Of: odoo/odoo#271850 Forward-Port-Of: odoo/odoo#271473
This change prevents overtime periods from overlapping when an employee’s attendance spans more than one day. It avoids an error that could interrupt work entry generation and ensures overtime is calculated correctly, especially around day boundaries.
Original PR description
**Problem:** When an attendance has overtimes across multiple days, those overtimes can overlap when calculating their intervals. There will always be rounding errors since only the durations are…
**Problem:** When an attendance has overtimes across multiple days, those overtimes can overlap when calculating their intervals. There will always be rounding errors since only the durations are saved to 3 decimals, but this is normally fine since the durations are accumulated when calculating the next interval. However, on a day boundary in the employee timezone, the end of the interval is forced to the end of day, which incidentally removes the rounding error. This causes the overlap when calculating the next interval since its start will be based on the rounded duration, not the actual end of day. **Steps to Reproduce:** - Configure an overtime rule where >8 hours is considered overtime, and a second rule applies to non-working days - Set Overtime Rule on employee "Anita Oliver" - Set employee work entry source to "Attendances" - Create an attendance that exceeds 8 hours in a day and crosses into a non-working day and creates enough of a rounding error (see unit test) -> Traceback error: `ValueError: Expected singleton: hr.attendance.overtime.line(1, 2)` **Solution:** Add an additional check to ensure the overtime cannot start on the previous day. opw-6067969 Forward-Port-Of: odoo/enterprise#119672 Forward-Port-Of: odoo/enterprise#118570
This update fixes an issue in the Time Off calendar view where users could not always scroll all the way to the bottom of the page. It improves the reliability of the page so employees can navigate the calendar more easily and reach all content as expected.
Original PR description
This PR expected to solve scrolling issue in Calender View Time Off module. In the Time Off module's Calender View, users aren't able to scroll down all the way to the bottom page. This behavior is intermittent so it's not deterministic. Root cause: This bug occurred in the earlist version and it might be related to an updated of Framework JS. task: 6328706
This update makes module installation more reliable when some referenced records were deleted earlier. It also fixes a case where new chart-of-accounts data could be incorrectly ignored during first-time setup, helping ensure accounting settings are applied as expected.
Original PR description
Installing a new module should be safe even when the module contains new data for records that have been deleted. It is not the responsibility of the localization to make sure of that. The fix in `l10n_sa_edi` had 2 issues: * calling `self.env.ref` instead of `self.ref` * Checking for the existence of records even in the case of installing the CoA for the first time on a company, which obviously doesn't contain anything. This results in always ignoring the data. Forward-Port-Of: odoo/odoo#271818
This update prevents the Czech accounting report setup from trying to take over records that already exist when reloading the chart of accounts. It helps avoid conflicts during setup and keeps existing accounting data safer and more consistent.
Original PR description
It is the burden of the CoA framework to check for that. See community commit for more information. Forward-Port-Of: odoo/enterprise#121643
The Mozambique demo company now uses a valid NUIT number. This prevents validation errors when newer standard number checks are applied, helping demo data load correctly and avoiding build failures.
Original PR description
Newer versions of stdnum (2.2) also test the number for MZ We did not have a valid NUIT number in the MZ demo company. Runbot error: https://runbot.odoo.com/runbot/build/114118067 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271398 Forward-Port-Of: odoo/odoo#271299
The system now only detaches attachments when that is appropriate for outgoing invoices. Incoming XML files received through EDI stay linked to bills so they can still be included in bulk exports, while the special Italian Tax Integration XML flow continues to work correctly.
Original PR description
The feature introduced in odoo/enterprise#78429 allows users to detach attachments from moves, primarily to facilitate the regeneration and re-sending of outgoing XMLs (e.g., sales invoices) without needing to delete the original attachment. However, detaching should not apply to incoming XML attachments on bills that originate from EDI import, as these attachments are the received source document and are never regenerated by the system. Detaching them inadvertently prevents their inclusion in bulk XML exports. An exception exists for Italy: businesses need to send Tax Integration XMLs back to the SdI. In this specific case, detaching the Tax Integration XML is appropriate and ensures the bulk export finds the latest, correct attachment. Ticket [link](https://www.odoo.com/odoo/project.task/5062132) opw-5062132 Forward-Port-Of: odoo/odoo#270896 Forward-Port-Of: odoo/odoo#239701
This update fixes an issue where adding an image to a vendor bill could block users from opening bill options or printing the original bill. It ensures image attachments are handled correctly so everyday accounting actions continue to work without access errors.
Original PR description
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a…
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a demo user. - Open the same vendor bill. - Click the gear icon. **Observation:** An access error is raised, and the gear icon is not accessible. **Root Cause:** At [1], the method `_should_attach_to_record` incorrectly excludes image attachments, causing them to be treated as `extra_files_data` at [2]. As a result, in `_fix_attachments_on_record_from_files_data` at [3], these attachments are assigned `res_model=False` and `res_id=0`. When the code tries to access these attachments at [4], it leads to an access error. Additionally, when we try to print `Original Bills`, we get the same access error at [5], and later the code calls the `browse` function on `self.env[attachment.res_model]`, but for `extra_files_data` we set the `res_model=False`, which results in a `KeyError`(see [6]). **Fix:** This commit prevents the error and ensures that users can access the gear icon when an image is attached in the chatter and print the `Original Bills`. [1]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L416-L429 [2]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_move.py#L6668-L6672 [3]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L409-L414 [4]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/account_move.py#L6944-L6949 [5]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/ir_actions_report.py#L30-L34 [6]: https://github.com/odoo/odoo/pull/261463#issuecomment-4602692978 opw-6119155 Forward-Port-Of: odoo/odoo#261463
The embedded Mercado Pago payment form now follows the website’s language instead of always appearing in English. This creates a more consistent checkout experience for customers and can help reduce confusion during payment.
Original PR description
The Mercado Pago Bricks SDK was always initialized with the `en-US` locale, so the embedded (inline) payment form rendered in English for every customer regardless of their website language. Resolve the Bricks locale from the website language instead. The locale is keyed by country, since each supported country maps to a single locale (e.g. Brazil is always pt-BR), so the language's country part is enough to resolve it. For the shared es_419 language, which carries no country, fall back on the company's country, and default to en-US for unsupported languages. task-6281783 Forward-Port-Of: odoo/odoo#269406
This update corrects a problem where new accounting tags weren't being properly applied during the Danish localization module's setup. Moving the tag mapping process to occur after the database is loaded ensures all tags are present, preventing errors and data inconsistencies. This resolves a foreign key violation that previously caused issues with account cleanup.
Original PR description
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent…
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent cleanup to fail with a FK violation on account_account_account_tag.
```py
File "/home/odoo/src/odoo/saas-19.2/odoo/sql_db.py", line 417, in execute
self._obj.execute(query, params)
psycopg2.errors.ForeignKeyViolation: update or delete on table "account_account_tag" violates foreign key constraint "account_account_account_tag_account_account_tag_id_fkey" on table "account_account_account_tag"
DETAIL: Key (id)=(356) is still referenced from table "account_account_account_tag".
```
Moving to post-migrate ensures all new account tags are present in the database before the remapping and cleanup run.
upg-[4341331]
[4341331]: https://upgrade.odoo.com/odoo/upgrade.request/4341331?debug=1
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269809This update fixes an issue where rental prices weren't correctly formatted on the website, appearing without the necessary slash separator. The fix ensures that rental prices and durations are displayed clearly and accurately, improving the user experience for customers renting products. This resolves a visual inconsistency.
Original PR description
Steps to produce: --- - Install the `Rental and eCommerce `modules. - Create a rental product and configure a rental price for it. - Add an optional product from the Sales tab. - Publish the product…
Steps to produce: --- - Install the `Rental and eCommerce `modules. - Create a rental product and configure a rental price for it. - Add an optional product from the Sales tab. - Publish the product on the website. - Open the product page on the website and click` Add to Cart`. Issue: --- - In the product configurator, the rental price is displayed without the `/` separator between the price and the rental duration period. Cause: --- - The string used to generate the rental duration label does not include the `/` separator. Fix: --- - Add the missing `/` separator to the rental duration label so that rental prices are displayed correctly. Before: --- <img width="974" height="185" alt="image" src="https://github.com/user-attachments/assets/64a88a60-bcc0-4657-97fd-584da57d0aff" /> After: --- <img width="967" height="188" alt="image" src="https://github.com/user-attachments/assets/b4d50019-1db4-4817-a8ce-446cc3c55df4" /> opw-6293015 Forward-Port-Of: odoo/enterprise#121246 Forward-Port-Of: odoo/enterprise#120223
This update fixes an issue where customer addresses in the Field Service kanban view would be cut off and displayed incorrectly due to a design element that didn't properly constrain the address width. The fix ensures that long customer addresses now fit neatly within the kanban card, improving readability and usability. This improves the visual presentation of customer information.
Original PR description
Steps to reproduce: - 1. Open the Field Service planning view in kanban. 2. Make sure a shift's customer has a long address (long street lines). 3. Look at that shift's card in the kanban view. Issue: - The customer address overflows the card and is clipped at its right edge instead of staying within the card boundaries. Cause: - The customer is rendered with the `many2one` widget and `show_address`, which marks each address line `text-truncate`. Truncation only works inside a width-bounded container, but the field root `.o_field_many2one` is an inline-flex item with the default `min-width: auto`, so it grows to fit the longest address line instead of shrinking to the card. As a result, `text-truncate` never engages and the address spills past the card. Fix: - Add the `min-w-0` class to the partner field so the flex item shrinks to the available card width. task-6272209 Forward-Port-Of: odoo/enterprise#119248
This update resolves an issue where Purchase Orders remained flagged as 'Late Receipts' even after a backorder was cancelled. The fix now correctly excludes both 'done' and 'cancel' pickings when determining if a purchase order is overdue, ensuring accurate reporting and a cleaner user experience. This prevents unnecessary alerts and improves order management.
Original PR description
Steps to reproduce: ------------------- - Create a Purchase Order with an expected Arrival date in the past - Confirm the Purchase Order - Validate the receipt partially and create a backorder -…
Steps to reproduce: ------------------- - Create a Purchase Order with an expected Arrival date in the past - Confirm the Purchase Order - Validate the receipt partially and create a backorder - Cancel the generated backorder - Open the Purchase Orders list and check the 'Late Receipts' Issue: ------ The Purchase Order still appears in the 'Late Receipts' filter even though there is no remaining receipt to process. Cause: ------ The 'Late Receipts' filter relies on the computed search field `is_late`: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase/views/purchase_views.xml#L439 The search domain for this field is generated by `purchase.order._search_is_late()`: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase/models/purchase_order.py#L176 In `purchase_stock`, `_get_domain_is_late()` extends the base domain to identify Purchase Orders that still have receipts pending: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase_stock/models/purchase_order.py#L264-L267 After a partial receipt: - the original receipt is in state `done`, - a backorder is created and linked to the Purchase Order, - the backorder is later cancelled and moves to state `cancel`, - the Purchase Order line still has `qty_received < product_qty`. The existing domain excludes only `done` pickings when determining whether a receipt is still pending. As a result, a cancelled backorder is still treated as an unfinished receipt, causing the Purchase Order to remain visible in the 'Late Receipts' filter. Fix: ---- Exclude both `done` and `cancel` pickings when determining whether a Purchase Order has pending receipts. A cancelled backorder indicates that the remaining quantity will not be received through that transfer. Therefore, once all related pickings are either completed or cancelled, the Purchase Order should no longer be considered late. --- opw-6266046 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268488
17 changes
Resolved issues and error corrections
This fix makes module installation more reliable when some referenced records were deleted earlier. It also corrects how Saudi localization data is checked during accounting setup, so valid initial setup data is no longer skipped by mistake.
Original PR description
Installing a new module should be safe even when the module contains new data for records that have been deleted. It is not the responsibility of the localization to make sure of that. The fix in `l10n_sa_edi` had 2 issues: * calling `self.env.ref` instead of `self.ref` * Checking for the existence of records even in the case of installing the CoA for the first time on a company, which obviously doesn't contain anything. This results in always ignoring the data. Forward-Port-Of: odoo/odoo#271818
This update prevents invoice imports from failing when a UBL line has no quantity and no line amount, even if a unit price is present. These lines are now skipped safely, so valid supplier files import without showing an error in the chatter.
Original PR description
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an…
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an import error Such lines are valid UBL but carry no meaningful value, so they are silently skipped after the fix ### Cause: After this commit: https://github.com/odoo/odoo/commit/a7f77f3cfc42764328e7da73a60df8d4cafc968f The `line_extension_amount` was able to go in new parts of the code with a 0.0 value When `line_extension_amount` is set and `invoiced_quantity` is 0, `quantity` is computed as `subtotal * price_quantity / (...)` which resolves to 0 since `subtotal` is also 0 `price_unit = subtotal / quantity` then divides by zero ### Steps to reproduce: - Install `l10n_be` - Import a UBL invoice with a line where `LineExtensionAmount=0`, `InvoicedQuantity=0` and `PriceAmount` is non-zero (You can use the xml on the ticket) Before the fix, the import failed with an error in the chatter opw-6234453 Forward-Port-Of: odoo/odoo#271001
This update prevents a crash that could occur when opening the Contacts Accounting tab in Studio for contacts with bank accounts. The bank tag component is now aligned with the read-only behavior of the parent field, so the page opens normally instead of showing an error.
Original PR description
When opening Studio → Contacts → Accounting Tab, Owl raises the following error: ```py Odoo Client Error Occured on 114697239-saas-19-2-all.runbot254.odoo.com on 2026-06-19 07:01:00 GMT…
When opening Studio → Contacts → Accounting Tab, Owl raises the following error:
```py
Odoo Client Error
Occured on 114697239-saas-19-2-all.runbot254.odoo.com on 2026-06-19 07:01:00 GMT
UncaughtPromiseError > OwlError
Uncaught Promise > Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
OwlError: Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
Error: Invalid props for component 'BankTag': 'onDelete' is undefined (should be a value)
at Object.validateProps (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1001:67)
at FieldMany2ManyTagsBanks.slot1 (eval at compile (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1387:421), <anonymous>:16:13)
at callSlot (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:968:25)
at TagsList.template (eval at compile (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:1387:421), <anonymous>:22:30)
at Fiber._render (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:797:96)
at Fiber.render (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:796:6)
at ComponentNode.initiateRender (https://114697239-saas-19-2-all.runbot254.odoo.com/web/assets/5482857/web.assets_web.min.js:867:47)
```
Note: The error only occurs when the contact has at least one bank accounts (bank_ids) in the Accounting tab.
`FieldMany2ManyTagsBanks` inherits from `Many2ManyTagsField`, whose `getTagProps()` [method](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js#L165-L173) intentionally sets `onDelete` to [undefined](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js#L168) when the field is rendered in readonly mode.
However, `BankTag` declares `onDelete` as a required [prop](https://github.com/odoo/odoo/blob/saas-19.2/addons/account/static/src/components/many2many_tags_banks/many2many_tags_banks.js#L18). Since Studio renders the field as readonly, `onDelete` is undefined, causing Owl prop validation to fail.
Make `onDelete` optional in `BankTag` to match the behavior of the parent widget and the underlying `BadgeTag` component, which already defines `onDelete` as [optional](https://github.com/odoo/odoo/blob/saas-19.2/addons/web/static/src/core/tags_list/badge_tag.js#L12).
This fixes the Owl error when opening the Accounting tab in Studio.
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-prThis update fixes an issue in the Time Off calendar view where users could sometimes not scroll all the way to the bottom of the page. It improves the reliability of browsing time-off entries and makes the view easier to use.
Original PR description
This PR expected to solve scrolling issue in Calender View Time Off module. In the Time Off module's Calender View, users aren't able to scroll down all the way to the bottom page. This behavior is intermittent so it's not deterministic. Root cause: This bug occurred in the earlist version and it might be related to an updated of Framework JS. task:6328706
This update fixes several issues in cash payment handling for the Point of Sale, including expired payment sessions, clearer error handling when cash cannot be returned, and faster failure detection when the payment device is unavailable. It also improves the cancellation flow, helping the cashier complete or stop transactions more reliably.
Original PR description
First issue: While paying if a user takes more than 15min the token is revoked. Second issue: When cancelling a payment where a user has already inserted money and there is an issue with giving back the money, no popup was shown on the PoS. Third issue: Fetch took too long when the device was not reacheable. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268296
This change fixes a performance issue in the HTML editor where very large documents could freeze the page or trigger a JavaScript error. It improves reliability and responsiveness when working with complex content.
Original PR description
For complex content, descendants(root) can return more than 100K elements. Using the spread operator expands all descendants into individual function arguments, which may exceed the JavaScript's argument limit and trigger a "Maximum call stack size exceeded" error. Replace with push() each node to the targetNodes. ||Before|After| |-|-|-| |getTargetNodes|Page Unresponsive|585 ms| Related ticket: opw-6303814 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271250
This fix prevents Point of Sale from failing with an error when a company does not have a country configured. It makes receipt data generation more resilient so users can continue working without interruptions.
Original PR description
### Description: Fix an unhandled exception linked to `vat_check` by using optional chaining. When a company does not have a country set, accessing `vat_check` throws an error because the parent object is undefined. ### Reference: opw-6321507 ___ I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale sessions can now be closed even when there are draft orders scheduled later on the same day. This fixes an issue where the system incorrectly blocked closing by only checking whether orders were in a future date, not whether they were later in the day.
Original PR description
A POS session could not be closed if there were draft orders planned for later the same day. The backend check was only filtering out orders with a date strictly in the future, ignoring the time part for same-day orders. task-id: 6000698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253433 Forward-Port-Of: odoo/odoo#251935
The Mozambique demo company now uses a valid NUIT tax number. This prevents validation errors in updated standard number checks and keeps demo data working correctly.
Original PR description
Newer versions of stdnum (2.2) also test the number for MZ We did not have a valid NUIT number in the MZ demo company. Runbot error: https://runbot.odoo.com/runbot/build/114118067 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271398 Forward-Port-Of: odoo/odoo#271299
This update prevents the planning process from failing when a shift has no start or end date. It adds a safeguard so auto-planning and sending actions only run when the required dates are available, improving reliability for users.
Original PR description
Add a guarding condition to the auto-plan or send behavior to avoid doing those operations when no start/end dates are defined --- Task: 6312650
This update fixes an error that could block users from opening the settings menu on a vendor bill when an image had been posted in the chatter. It also ensures printing the original bill works correctly, improving reliability for users who review and process bills.
Original PR description
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a…
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a demo user. - Open the same vendor bill. - Click the gear icon. **Observation:** An access error is raised, and the gear icon is not accessible. **Root Cause:** At [1], the method `_should_attach_to_record` incorrectly excludes image attachments, causing them to be treated as `extra_files_data` at [2]. As a result, in `_fix_attachments_on_record_from_files_data` at [3], these attachments are assigned `res_model=False` and `res_id=0`. When the code tries to access these attachments at [4], it leads to an access error. Additionally, when we try to print `Original Bills`, we get the same access error at [5], and later the code calls the `browse` function on `self.env[attachment.res_model]`, but for `extra_files_data` we set the `res_model=False`, which results in a `KeyError`(see [6]). **Fix:** This commit prevents the error and ensures that users can access the gear icon when an image is attached in the chatter and print the `Original Bills`. [1]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L416-L429 [2]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_move.py#L6668-L6672 [3]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L409-L414 [4]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/account_move.py#L6944-L6949 [5]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/ir_actions_report.py#L30-L34 [6]: https://github.com/odoo/odoo/pull/261463#issuecomment-4602692978 opw-6119155 Forward-Port-Of: odoo/odoo#261463
The embedded Mercado Pago payment form now appears in the customer’s website language instead of always showing in English. This makes checkout clearer and more consistent for shoppers, especially in multilingual websites.
Original PR description
The Mercado Pago Bricks SDK was always initialized with the `en-US` locale, so the embedded (inline) payment form rendered in English for every customer regardless of their website language. Resolve the Bricks locale from the website language instead. The locale is keyed by country, since each supported country maps to a single locale (e.g. Brazil is always pt-BR), so the language's country part is enough to resolve it. For the shared es_419 language, which carries no country, fall back on the company's country, and default to en-US for unsupported languages. task-6281783 Forward-Port-Of: odoo/odoo#269406
Vendor bills in foreign currencies are now matched correctly against GSTR-2B values reported in INR. This prevents bills from being incorrectly flagged as partially matched and improves the accuracy of GST reconciliation.
Original PR description
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set…
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set an exchange rate. * Create a new vendor bill for an Indian vendor, setting the currency to USD. * Add lines to the bill and apply IGST/GST taxes, then confirm the bill. * Go to **Accounting → Reporting → GST Return Period** and initiate GSTR-2B matching for the period corresponding to the bill (using a valid JSON payload where the amounts are correctly reported in INR). **Observed behavior:** * The vendor bill is incorrectly marked as "Partially matched" instead of "Fully matched", accompanied by an exception stating that the total amount as per GSTR-2B does not match. **Cause:** * The GSTR-2B data fetched from the GST portal always reports values in the company's base currency (INR). * The `match_bills` method was directly comparing the GSTR-2B INR amounts ( `bill_total` and `bill_taxable_value`) against the bill's `amount_total` and `amount_untaxed` fields. * Because these fields return values in the document's foreign currency (e.g., USD), the mismatch triggers an exception and flags the bill as partially matched. **Fix:** * Modified the matching logic to compare GSTR-2B values against `abs(amount_total_signed)` and `abs(amount_untaxed_signed)`. * This ensures that the amounts evaluated during reconciliation are always correctly converted and compared in the company's base currency (INR). opw-6311097 Forward-Port-Of: odoo/enterprise#121677 Forward-Port-Of: odoo/enterprise#120967
This update makes manufacturing work order time calculations more accurate by only counting actual productive work and by avoiding double-counting when time intervals overlap. It also fixes a timing issue that could distort results when durations are recorded in quick succession, improving the reliability of cost and valuation calculations.
Original PR description
[[FIX] mrp: calculate real duration excluding non-productive intervals](https://github.com/odoo/odoo/pull/248381/changes/fac6b2540a32a015f56085c2c27ba4281eb659cf) and deduplicating overlaps * Current…
[[FIX] mrp: calculate real duration excluding non-productive intervals](https://github.com/odoo/odoo/pull/248381/changes/fac6b2540a32a015f56085c2c27ba4281eb659cf) and deduplicating overlaps * Current Situation: Currently real duration is total duration of each time tracking which is not consistent with the time that use to calculate the cost for valuation , see https://github.com/odoo/odoo/pull/205154 .The real duration of a work order was incorrectly summing all time tracking entries regardless of their loss type, and using simple addition which double-counts overlapping intervals. * Solution: - Filter time entries to only 'productive' and 'performance' loss types, excluding 'availability' and 'quality' as they represent downtime/blocking time, not actual work duration. - Pool all productive and performance entries into a single Intervals call so that overlaps across both types are merged in one pass. Note: the enterprise17 implementation groups time entries by loss_type into separate buckets before calling Intervals, which means overlaps between 'productive' and 'performance' entries are not merged and get double-counted. Pooling both types together before the Intervals call avoids this. * This also fix: - Fix _set_duration to ensure newly created time entries start after the latest existing entry's end date. Without this, calling _set_duration twice in quick succession (e.g. in tests) produces two entries with overlapping timestamps, which Intervals correctly merges into one, causing the computed duration to be half the expected value. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248381
This update corrects a problem where new accounting tags weren't being properly processed during an update, leading to database errors. By moving the tag remapping process to occur after the module's data is loaded, the system now correctly handles all new tags and avoids the previous database conflicts.
Original PR description
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent…
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent cleanup to fail with a FK violation on account_account_account_tag.
```py
File "/home/odoo/src/odoo/saas-19.2/odoo/sql_db.py", line 417, in execute
self._obj.execute(query, params)
psycopg2.errors.ForeignKeyViolation: update or delete on table "account_account_tag" violates foreign key constraint "account_account_account_tag_account_account_tag_id_fkey" on table "account_account_account_tag"
DETAIL: Key (id)=(356) is still referenced from table "account_account_account_tag".
```
Moving to post-migrate ensures all new account tags are present in the database before the remapping and cleanup run.
upg-[4341331]
[4341331]: https://upgrade.odoo.com/odoo/upgrade.request/4341331?debug=1
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269809This update resolves a technical issue preventing the Spanish E-Invoice module (l10n_es_edi_verifactu) from functioning correctly during upgrades. The fix ensures the necessary 'certificate' module is loaded first, preventing a critical error that blocked the module's operation. This ensures a smoother upgrade process and correct functionality for users utilizing the Spanish E-Invoice feature.
Original PR description
### Issue `l10n_es_edi_verifactu` builds an inheritance on `certificate.certificate` and loads that module's views/demo, but only declares `depends: ['l10n_es']`. With `certificate` not guaranteed to…
### Issue `l10n_es_edi_verifactu` builds an inheritance on `certificate.certificate` and loads that module's views/demo, but only declares `depends: ['l10n_es']`. With `certificate` not guaranteed to load first, building the registry without it already present raises: ``` TypeError: Model 'certificate.certificate' does not exist in registry. ``` ### Cause `models/certificate.py` → `_inherit = 'certificate.certificate'`; manifest `data` loads `views/certificate_certificate_views.xml` and `demo/demo_certificate.xml`. Yet `certificate` is absent from `depends`. Every sibling (`l10n_es_edi_facturae`/`sii`/`tbai`, `l10n_sa_edi`) already depends on `certificate`. Present since the module was added in `02f8d5525eb7`. ### Notes - Opened on **18.0** so it **forward-ports to 19.0** (both stable branches carry the bug). `master` already has the equivalent change via #234729 — the forward-port there should be a no-op. - Surfaced via an 18.0→19.0 OpenUpgrade migration that force-updates `verifactu` before `certificate` loads; also reproducible on a plain install where `certificate` isn't otherwise pulled in first. Forward-Port-Of: odoo/odoo#271827 Forward-Port-Of: odoo/odoo#271496
The Time Off Balance report was incorrectly calculating remaining days when overlapping allocations existed. This fix ensures the report accurately reflects the remaining time off by correctly deducting leaves from overlapping allocations. This resolves a discrepancy between the reported balance and the actual available time.
Original PR description
The Time Off Balance report shows incorrect remaining days when overlapping allocations exist and a leave only overlaps the later one. ### **Steps to reproduce:** 1) Install time off app. 2) Create a…
The Time Off Balance report shows incorrect remaining days when overlapping allocations exist and a leave only overlaps the later one. ### **Steps to reproduce:** 1) Install time off app. 2) Create a simple time off type. - Create Allocation A (10 days, 01-01-2024 to 31-12-2025) - Create Allocation B (10 days, 01-01-2025 to 31-12-2026) 3) Create a leave of 1 day on 01-01-2026 4) Open the Balance report ### **Observed Behavior:** The report shows 20 remaining days. ### **Expected Behavior:** The report should show 19 remaining days (20 allocated - 1 taken). ### **Cause:** In the taken_per_allocation CTE at [1], each leave is joined to every allocation it overlaps. The [fifo_balances] CTE then uses the formula: ``` GREATEST(alloc_days - GREATEST(taken - prior_cumulative_alloc, 0), 0) ``` This subtracts the prior allocation capacity (A = 10 days) from the taken count (B = 1 day). Since 1 - 10 = -9, GREATEST(-9, 0) = 0, so zero days are deducted from B. The formula wrongly assumes that prior allocations can absorb leaves that do not overlap with them. [1]- https://github.com/odoo/odoo/blob/f0fa79fa21d2005dd5cd132c18b2be45424166a6/addons/hr_holidays/report/hr_leave_employee_type_report.py#L126-L142 [fifo_balances]: https://github.com/odoo/odoo/blob/f0fa79fa21d2005dd5cd132c18b2be45424166a6/addons/hr_holidays/report/hr_leave_employee_type_report.py#L145-L164 ### **Fix:** Ensure that leaves are only deducted from allocations they actually overlap by calculating the balance using the delta of cumulative leaves within an overlap group. This prevents earlier allocations from absorbing leaves that occur outside their validity period. **opw-6150161** Forward-Port-Of: odoo/odoo#271596 Forward-Port-Of: odoo/odoo#263029
32 changes
Resolved issues and error corrections
This change prevents some bank transaction records from being created twice when the scheduled import runs. It restores the previous behavior so already-imported files are not processed again, reducing duplicate draft entries for users.
Original PR description
Since this commit: https://github.com/odoo/enterprise/commit/a0c9e9b5c0ed8135d77c343c819c1fa918356794 users are experiencing some duplicate draft move when the cron is running. It's because we don't skip the files when it already exist, we now add a number of imported count. This commit will revert this change to avoid the problem, and we will contact codabox to find a better way to deal with files imported the same month. task-6299508
The mailing theme selector now refreshes both the title and the preview when switching between favorite templates for different target models. This prevents users from seeing a mismatched preview and helps them choose the right mailing template more reliably.
Original PR description
Overview ------ When having a favorite mailing (template) for target model X, and another one for target model Y, and try to create a new mailing for target model X, the theme selector will first…
Overview ------ When having a favorite mailing (template) for target model X, and another one for target model Y, and try to create a new mailing for target model X, the theme selector will first show the template X with the correct title and preview, however when switching to model Y, the theme selector will show the title of the tempalte Y but the preview is always the one of template X. How to reproduce ------ 1. Create a new mailing for a target model X (e.g. `mailing.contact`) 2. Set a content for that mailing (you can choose from the existing themes) 3. Set that mailing as a favorite (using the favorite star button) 4. Create a new mailing for another target model Y. 5. Redo steps 2. and 3. 6. Create a new mailing, and set the target model to X (You should see the mailing X in the theme selector with the correct title and preview) 7. Change the target model to Y. Expected Behavior ------ Both the title and the preview of the mailing X in the theme selector should change into the title and the preivew of mailing Y. Current Behavior ------ The title of the template is changed into the one of Y however the preview remains the one of mailing X. Cause of The Issue ------ After the first mount of the `FavoritePreivew` component, when the template changes in the props, the body content of the preivew is not updated with the new value. Task-6332946 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The page limit note in the website generator has been updated to use more general wording instead of a fixed number. This gives the system more flexibility to adjust page limits later without misleading users.
Original PR description
Page limit note fixed by being more general instead of stating a blatant 200. This gives us more leeway to control the nbr of pages IAP side.
This fix ensures blue map cluster bubbles are removed properly when users zoom or pan on the customers map. It prevents old bubbles from piling up on the screen, improving map clarity and making the page easier to use.
Original PR description
Steps to reproduce: =================== 1. Install website_customer, set a Google Maps API key and publish a few companies with coordinates 2. Open /customers 3. Open the map and zoom in a few times…
Steps to reproduce: =================== 1. Install website_customer, set a Google Maps API key and publish a few companies with coordinates 2. Open /customers 3. Open the map and zoom in a few times => stale blue cluster bubbles remain on the map Cause: ====== On the partner map, zooming or panning left old cluster bubbles behind: the blue count icons piled up and never disappeared, even at the closest zoom level. `ClusterIcon` is meant to be a google.maps.OverlayView. The bundled `markerclusterer.js` wires that up by copying every enumerable https://github.com/odoo/odoo/blob/aed1619c34b1f65bd9a3d155fe76a82d404ef5e7/addons/website_google_map/static/src/lib/markerclusterer.js#L213-L221 OverlayView.prototype member onto ClusterIcon.prototype. Google Maps now ships its own OverlayView.prototype.remove, and that copy overwrites ClusterIcon's own `remove()` with it, As a result, when a cluster icon is removed, `ClusterIcon.remove()` is never executed. Consequently, `ClusterIcon.prototype.onRemove()` is not triggered, the cluster icon's DOM element is never detached from the map, https://github.com/odoo/odoo/blob/aed1619c34b1f65bd9a3d155fe76a82d404ef5e7/addons/website_google_map/static/src/lib/markerclusterer.js#L1167 and stale cluster bubbles accumulate after every redraw, zoom, or pan operation. Solution: ========= Inherit from OverlayView through the prototype chain instead of copying it, so ClusterIcon's own remove() is kept and actually detaches the icon. opw-6128531 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270733
This update extends an existing test safeguard so the accounting dashboard checks also block the newer Odoo Fin v2 endpoint. It helps keep automated tests fully isolated from live services, reducing the risk of unintended external requests during testing.
Original PR description
This commit follows up on [1] by extending the Odoo Fin request mock to cover the new version 2 (v2) favorite institutions endpoint. Previously, a mock was introduced to prevent the Clickall tool from making real external HTTP requests to `production.odoofin.com` when displaying the accounting dashboard. This update ensures that the newly introduced v2 URL is also safely intercepted, keeping the automated tests fully isolated from production servers. runbot-234936 [1] : https://github.com/odoo/odoo/commit/c6451015f1b01c3e1defe4a576989fd4bfdf2cdb Forward-Port-Of: odoo/odoo#271804
This fix ensures that when a purchase order quantity is reduced, the related incoming receipt is updated to the new lower amount instead of being increased incorrectly. It prevents mismatches between what was ordered and what the warehouse expects to receive, which helps avoid fulfillment errors.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Routes - Unarchive MTO - Create a storable product P with MTO buy and a set…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Routes - Unarchive MTO - Create a storable product P with MTO buy and a set vendor - Create and confirm a sale order for 1 unit of P - Confirm the assocaited PO and change the pol quantity from 1 to 10 > the associated receipt is updated from 1 to 10 - Change the pol quantity from 10 to 7 #### > The quantity on the receipt is updated from 10 to 16. ### Cause of the issue: Changing the quantity of the POL will adapt the picking related quantity via these lines: https://github.com/odoo/odoo/blob/3bf89b4f467390807c20f7b007a875a77542e76f/addons/purchase_stock/models/purchase_order_line.py#L115-L117 https://github.com/odoo/odoo/blob/3bf89b4f467390807c20f7b007a875a77542e76f/addons/purchase_stock/models/purchase_order_line.py#L342-L349 by creating new stock moves to be merged: https://github.com/odoo/odoo/blob/3bf89b4f467390807c20f7b007a875a77542e76f/addons/purchase_stock/models/purchase_order_line.py#L220-L251 Now, the issue is that this flows relies both on a negative `qty_to_attach` of `1 - 10 = -9` and a positive `qty_to_push` of `7 - 1 = 6`. However, the `qty_to_attach` is only used if is positive: https://github.com/odoo/odoo/blob/3bf89b4f467390807c20f7b007a875a77542e76f/addons/purchase_stock/models/purchase_order_line.py#L243-L251 The receipt is therefore updated by a `+6` move to push but not by the `-9` move to attach. Leading to a 10 -> 16 rather than 10 -> 7 result. opw-6218307 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270547 Forward-Port-Of: odoo/odoo#264994
This change stops the system from repeatedly rescheduling automatic posting jobs when a batch contains records that cannot be posted. Failed records are now marked so they are not retried over and over, reducing unnecessary background processing and improving system efficiency.
Original PR description
Before this change, cron jobs triggering `_autopost_draft_entries` would gracefully handle batch-level failures by logging the error and retry one by one. As a result, `_process_job`, with success 0 done and remaining number, marked the cron run as partially completed and triggered `_reschedule_asap`. When a batch contained only problematic records, the cron job could be rescheduled thousands of times per day. With this change, if a move in the batch fails to post, we set its `auto_post` to `no`, together with the existing message-posting logic in the chatter, to prevent repeated retries for failed records. Related ticket: opw-6303194 opw-5364851 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271509
Employees with flexible schedules can now request a one-day leave on a public holiday when that leave type counts public holidays in its duration. This fixes a case where the request was previously rejected even though longer leave requests already worked as expected.
Original PR description
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is…
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is rejected. ### **Steps to reproduce:** - Create a public holiday. - Create a time off type with "Public Holiday Included" enabled. - Select/create an employee with a flexible work schedule and its time zone must be same as admin. - Request a time off on the public holiday date only. ### **Observed Behavior:** The request is rejected because its duration is computed as 0 days. ### **Expected Behavior:** The request should be allowed and count as 1 day, consistent with the multi-day request behavior. ### **Root Cause:** At [1], a dedicated duration computation path is used for single-day leaves of flexible employees. This logic always retrieves overlapping public holidays and computes the leave duration based on the remaining intervals. As a result, a leave requested entirely on a public holiday is computed as 0 days, even when `include_public_holidays_in_duration` is enabled. [1]- https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/hr_holidays/models/hr_leave.py#L436-L444 ### **Fix:** This commit ensures that the `include_public_holidays_in_duration` setting is taken into account when computing single-day leave durations for flexible employees **opw-6284768** Forward-Port-Of: odoo/odoo#271594 Forward-Port-Of: odoo/odoo#269743
The Forecasted Demand edit button now stays visible even when the Forecasted Stock row is hidden in Master Production Schedule. This fixes a confusing display issue so users can still access forecast suggestions without changing unrelated row visibility.
Original PR description
Steps to reproduce:
1. Install Manufacturing.
2. Enable 'Master Production Schedule' in the Settings.
3. Go to [Manufacturing -> Planning -> Master Production Schedule].
4. Ensure 'Demand Forecast' and 'Forecasted Stock' rows are enabled from the dropdown.
5. Observe the edit pencil button next to 'Forecasted Demand' is visible.
6. Hide 'Forecasted Stock' using the rows filter dropdown.
Issue:
The edit pencil button ("Suggest Forecasted Demand") next to the 'Forecasted Demand' row disappears when the 'Forecasted Stock' row is hidden.
Expected behavior:
The edit pencil visibility should not be affected by the 'Forecasted Stock' row.
opw-6240596
Forward-Port-Of: odoo/enterprise#120208Bank accounts linked to a partner can now be used in child companies even when that partner belongs to the parent company. This fixes a cross-company usability issue so shared business records work as expected in branch setups.
Original PR description
Even when a partner has the 'company_id' filled with the parent company, his bank account should be usable in the child companies. This was done in odoo/odoo#262173 from 19.2 but we need to backport it in stable task-6309694 Forward-Port-Of: odoo/odoo#271470
This change prevents a warehouse setup check from stopping module installation when a database has multiple companies and not all of them have a warehouse yet. As a result, installing stock-related features is smoother and no longer fails partway through in this common setup.
Original PR description
Steps to reproduce the bug:
- Have a database with sale_management installed and at least two companies (Company 1 and Company 2)
- Confirm sale orders with storable products under each company
- Install the stock module (which triggers sale_stock as a bridge module)
Problem:
The installation raised a RedirectWarning ("Please create a warehouse for company 2") and aborted. During sale_stock installation, _init_column initialises the new `warehouse_id` column on `sale.order` via SQL. Orders belonging to companies that have no warehouse yet (company 2, since `create_missing_warehouse` only creates one for the first company at that point) remain NULL. The stored-field recompute then calls write(), which fires _check_warehouse. That constraint calls _warehouse_redirect_warning() for each company without a warehouse, raising a RedirectWarning that aborts the install.
opw-6302537
Forward-Port-Of: odoo/odoo#270480This update fixes an issue in the Time Off calendar view where users could not always scroll all the way to the bottom of the page. As a result, the calendar now behaves more reliably and users can reach all content more easily.
Original PR description
This PR expected to solve scrolling issue in Calender View Time Off module. In the Time Off module's Calender View, users aren't able to scroll down all the way to the bottom page. This behavior is intermittent so it's not deterministic. Root cause: This bug occurred in the earlist version and it might be related to an updated of Framework JS. task:6328706
Helpdesk ticket status labels now stay consistent across list, form, and kanban views when a custom label is changed. This prevents staff from seeing different names for the same status depending on where they look, reducing confusion and making updates easier to trust.
Original PR description
Steps to reproduce: ------------------------ 1. Install Helpdesk 2. Go to All Tickets and check the kanban state selection value 3. Go to Settings > Field Selection and search for kanban_state in…
Steps to reproduce:
------------------------
1. Install Helpdesk
2. Go to All Tickets and check the kanban state selection value
3. Go to Settings > Field Selection and search for kanban_state in `helpdesk.ticket` model
4. Change one of the state selection values (e.g., "Ready" to "Testing Ready")
5. Go back and check the state selection value in list and form views
Current behavior:
-----------------------
Kanban view correctly shows the updated label (e.g., "Testing Ready"),
but list and form views still display the old default value (e.g., "Ready").
Root cause:
---------------
The [state_selection](https://github.com/odoo/odoo/blob/c09cefdb0ed68b1b7367b77b18a5ee5d66c94900/addons/web/static/src/views/fields/state_selection/state_selection_field.js#L57-L65) widget uses `legend_${state}` field values when available.
Since list and form views included these legend fields, the widget resolved labels from them
instead of the actual selection values, causing inconsistent display.
Fix:
-----
Remove `legend_normal`, `legend_blocked`, and `legend_done` fields from the list and form views,
So the widget falls back to the real selection labels, consistent with how the kanban view behaves.
Reference commit: https://github.com/odoo/enterprise/commit/65f3b88254e3a66e2c5dcb5142d30f6b1996d999
opw-6238765
Forward-Port-Of: odoo/enterprise#119707This change prevents the system from creating empty draft manufacturing orders for products that have no bill of materials. In these cases, replenishment rules will handle the request instead, which avoids unnecessary records and confusing production tasks.
Original PR description
Steps to reproduce: - unarchive the MTO route - Create a storable product "P1" with the MTO + Manufacture routes but set no Bill of Materials on it - Create a sales order with one unit of P1 and confirm it Problem: An empty draft MO is created even though no Bill of Materials exists. When no BoM is available, manufacturing orders should not be created, only replenishment rules are expected to handle this case. Fix: Added an early `continue` in `_run_manufacture` to skip MO creation when no BoM is found. opw-6174886 Forward-Port-Of: odoo/odoo#263108
This fix corrects the Time Off Balance report when an employee has overlapping time off allocations. Previously, a leave could be counted against the wrong allocation period, which could make the remaining balance appear too high; now the report deducts leave only from the allocations it actually overlaps, so balances are accurate.
Original PR description
The Time Off Balance report shows incorrect remaining days when overlapping allocations exist and a leave only overlaps the later one. ### **Steps to reproduce:** 1) Install time off app. 2) Create a…
The Time Off Balance report shows incorrect remaining days when overlapping allocations exist and a leave only overlaps the later one. ### **Steps to reproduce:** 1) Install time off app. 2) Create a simple time off type. - Create Allocation A (10 days, 01-01-2024 to 31-12-2025) - Create Allocation B (10 days, 01-01-2025 to 31-12-2026) 3) Create a leave of 1 day on 01-01-2026 4) Open the Balance report ### **Observed Behavior:** The report shows 20 remaining days. ### **Expected Behavior:** The report should show 19 remaining days (20 allocated - 1 taken). ### **Cause:** In the taken_per_allocation CTE at [1], each leave is joined to every allocation it overlaps. The [fifo_balances] CTE then uses the formula: ``` GREATEST(alloc_days - GREATEST(taken - prior_cumulative_alloc, 0), 0) ``` This subtracts the prior allocation capacity (A = 10 days) from the taken count (B = 1 day). Since 1 - 10 = -9, GREATEST(-9, 0) = 0, so zero days are deducted from B. The formula wrongly assumes that prior allocations can absorb leaves that do not overlap with them. [1]- https://github.com/odoo/odoo/blob/f0fa79fa21d2005dd5cd132c18b2be45424166a6/addons/hr_holidays/report/hr_leave_employee_type_report.py#L126-L142 [fifo_balances]: https://github.com/odoo/odoo/blob/f0fa79fa21d2005dd5cd132c18b2be45424166a6/addons/hr_holidays/report/hr_leave_employee_type_report.py#L145-L164 ### **Fix:** Ensure that leaves are only deducted from allocations they actually overlap by calculating the balance using the delta of cumulative leaves within an overlap group. This prevents earlier allocations from absorbing leaves that occur outside their validity period. **opw-6150161** Forward-Port-Of: odoo/odoo#271596 Forward-Port-Of: odoo/odoo#263029
This change stops command menu actions and markdown shortcuts from working inside code blocks. It helps users avoid unexpected errors and keeps code content from being accidentally reformatted while editing.
Original PR description
### Steps to reproduce: - Go to ToDo. - Create a code block using `/code`. - Place the cursor inside the code block. - Type `/table` and select the table command. - A traceback occurs. ### Purpose of this PR: - Commands and markdown shorthands should not be available inside code blocks. However, typing `/` inside a `<pre>` opened the command palette, allowing structural commands such as `/table` to be executed and causing a traceback. Similarly, markdown shorthands such as `* ` and `1.` were still active, unexpectedly transforming code content into lists. ### This PR fixes the issue by: - Disabling the command palette when the cursor is inside a `<pre>` element. - Disabling markdown shorthands inside `<pre>` elements by registering an `is_shorthand_available_predicates` predicate. task-6292231 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271695 Forward-Port-Of: odoo/odoo#269430
Tax unit members who are not the main company can now access tax return checks, so they can resolve issues affecting their return. The system also shows a warning when the selected companies do not match the companies included in a tax return, helping users avoid confusion and missing data.
Original PR description
[FIX] account_reports: show return checks to every tax unit member Before this commit: Tax Unit Members other than main company have read access to tax returns but don't have read access to tax return checks. After this commit: Tax Unit members other than main company are given read access to tax return checks also, so they can fix checks failing because of them. *** [IMP] account_reports: Warn on company mismatch in tax returns Adds a warning banner to the return kanban view, when the user's active companies do not match the companies on the return. Backport of: https://github.com/odoo/enterprise/commit/48fea3df68ec2cc9ed1ba538e1b480210611bcde *** task-5951364 Forward-Port-Of: odoo/enterprise#113118
This fix stops popup snippets from being placed inside other popups, which could break the editor and show errors. It also ensures the list of available snippets is updated correctly after changes, so users only see valid options.
Original PR description
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError:…
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError: Cannot read properties of undefined (reading 'after')`. This can happen in multiple scenarios: - After saving a custom snippet, the snippets are reloaded but `disableUndroppableSnippets` is not called again, although the snippets should be filtered again. - `NewsletterPopupPlugin` registers `.o_newsletter_popup` in the `so_snippet_addition_selector` resource, bypassing the more restrictive `dropzone_selector` of `PopupOptionPlugin`. - Popups are not disabled when the cookie bar is open because we don't take `excludeAncestor` into account in `DisableSnippetsPlugin`. __Fix__ - Trigger an event whenever the snippets are loaded and call `disableUndroppableSnippets` when it is. - Remove the redundant `NewsletterPopupPlugin`. - Filter `dropAreaEls` with `excludeAncestor` in `DisableSnippetsPlugin`. Forward-Port-Of: odoo/odoo#269864
This update resolves several issues in the Cashmatic payment flow to help the point of sale certification process. It prevents payment sessions from expiring too early, improves error handling when cash return fails, and avoids long waits when the device is unavailable. It also fixes payment cancellation behavior in forced-done cases.
Original PR description
First issue: While paying if a user takes more than 15min the token is revoked. Second issue: When cancelling a payment where a user has already inserted money and there is an issue with giving back the money, no popup was shown on the PoS. Third issue: Fetch took too long when the device was not reacheable. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268296
This fix prevents UBL invoice imports from failing when a line has no quantity and no line amount, even if a price is present. Instead of stopping the whole import with an error, these empty-value lines are now safely skipped, improving reliability for valid invoices.
Original PR description
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an…
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an import error Such lines are valid UBL but carry no meaningful value, so they are silently skipped after the fix ### Cause: After this commit: https://github.com/odoo/odoo/commit/a7f77f3cfc42764328e7da73a60df8d4cafc968f The `line_extension_amount` was able to go in new parts of the code with a 0.0 value When `line_extension_amount` is set and `invoiced_quantity` is 0, `quantity` is computed as `subtotal * price_quantity / (...)` which resolves to 0 since `subtotal` is also 0 `price_unit = subtotal / quantity` then divides by zero ### Steps to reproduce: - Install `l10n_be` - Import a UBL invoice with a line where `LineExtensionAmount=0`, `InvoicedQuantity=0` and `PriceAmount` is non-zero (You can use the xml on the ticket) Before the fix, the import failed with an error in the chatter opw-6234453 Forward-Port-Of: odoo/odoo#271001
This update prevents an error that could block users from opening certain vendor bills when an image was posted in the chatter. It also restores the ability to print original bills in these cases, improving day-to-day usability for accounting users.
Original PR description
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a…
**Steps to reproduce:** - Install the `accountant` module and log in as admin. - Create and confirm a vendor bill. - Send an image in the chatter of the vendor bill. - Open a new tab and log in as a demo user. - Open the same vendor bill. - Click the gear icon. **Observation:** An access error is raised, and the gear icon is not accessible. **Root Cause:** At [1], the method `_should_attach_to_record` incorrectly excludes image attachments, causing them to be treated as `extra_files_data` at [2]. As a result, in `_fix_attachments_on_record_from_files_data` at [3], these attachments are assigned `res_model=False` and `res_id=0`. When the code tries to access these attachments at [4], it leads to an access error. Additionally, when we try to print `Original Bills`, we get the same access error at [5], and later the code calls the `browse` function on `self.env[attachment.res_model]`, but for `extra_files_data` we set the `res_model=False`, which results in a `KeyError`(see [6]). **Fix:** This commit prevents the error and ensures that users can access the gear icon when an image is attached in the chatter and print the `Original Bills`. [1]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L416-L429 [2]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_move.py#L6668-L6672 [3]: https://github.com/odoo/odoo/blob/95864190a71b68eb10ae59ae8f38ac35b0cb6a97/addons/account/models/account_document_import_mixin.py#L409-L414 [4]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/account_move.py#L6944-L6949 [5]: https://github.com/odoo/odoo/blob/7e874e7db30e05a02d6eeb26d9d67ed6176b9704/addons/account/models/ir_actions_report.py#L30-L34 [6]: https://github.com/odoo/odoo/pull/261463#issuecomment-4602692978 opw-6119155 Forward-Port-Of: odoo/odoo#261463
When two table orders are merged, items that were already sent to the kitchen now keep their sent status instead of being treated as new. This prevents restaurant staff from having to resend unchanged quantities to the kitchen printer.
Original PR description
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was…
When transferring an order to a table that already has an open order, identical products are merged into a single line. If both orders were already sent to the kitchen printer, the merged line was incorrectly marked as new and had to be sent again. Steps to reproduce: ------------------- * Open table 1, add product A (2 units) and product B, send to kitchen * Open table 2, add product A (3 units) and product C, send to kitchen * On table 2, transfer/merge the order to table 1 > Observation: product A shows 2 units as new and must be sent to the kitchen printer again, although all quantities were already sent. Why the fix: ------------ When merging preparation history for identical lines, handlePreparationHistory overwrote the destination sent quantity with the source one instead of summing both. The kitchen diff then treated the missing quantity as new changes. A unit test will be added in 18.3. opw-6246470 Forward-Port-Of: odoo/odoo#271392 Forward-Port-Of: odoo/odoo#267915
This update prevents the web editor from freezing or crashing when users work with very large and complex content. It improves how editor elements are collected behind the scenes, making the page respond much faster in these cases.
Original PR description
For complex content, descendants(root) can return more than 100K elements. Using the spread operator expands all descendants into individual function arguments, which may exceed the JavaScript's argument limit and trigger a "Maximum call stack size exceeded" error. Replace with push() each node to the targetNodes. ||Before|After| |-|-|-| |getTargetNodes|Page Unresponsive|585 ms| Related ticket: opw-6303814 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271250
When a vendor bill is auto-completed from a purchase order, some invoice details can change and the related accounting entries need to be refreshed. This fix makes sure early payment discount lines are updated correctly, so invoice lines and journal entries stay aligned and avoid mismatches.
Original PR description
When a vendor bill is imported and auto-completed from a purchase order, then invoice lines, taxes, fiscal position, and payment terms can change. Existing EPD dynamic lines that lose their epd_key are skipped by sync and keep stale tax tags and amounts, causing mismatches between Invoice Lines and Journal Items. This commit makes EPD sync include keyless existing EPD lines so they are rewritten or removed during dynamic recomputation after PO auto-complete. Journal items remain consistent with the final invoice lines, taxes, and early discount configuration. Ticket [link](https://www.odoo.com/odoo/project.task/6047505) opw-6047505 Forward-Port-Of: odoo/odoo#271631 Forward-Port-Of: odoo/odoo#265539
This change ensures that when a field’s search index type is updated, existing databases are automatically refreshed to use the correct index format. It prevents older indexes from being left behind, which helps keep search performance consistent after upgrades.
Original PR description
Description of the issue/feature this PR addresses: `Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates…
Description of the issue/feature this PR addresses:
`Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates the index when no index of that name already exists. It never inspects the access method of an existing index.
As a consequence, changing a field's `index=` kind on an **already-indexed** column is silently ignored on existing databases. For example `account.move.name` was changed from a plain btree index to `index='trigram'`:
```python
name = fields.Char(
...
index='trigram',
)
```
On a fresh database this creates the expected GIN/trigram index. On any database that already had the btree index, the old btree index keeps its name, so `check_indexes` finds the name present and does nothing. The `(=)ilike` searches the trigram index was meant to accelerate keep falling back to sequential scans, with no error or warning.
Current behavior before PR:
### Steps to reproduce
1. Install a module on an existing DB while a `Char` field is `index=True` (btree).
2. Change the field to `index='trigram'` and upgrade the module.
3. `\d <table>` in psql — the index is still `USING btree`, not `USING gin`.
Desired behavior after PR is merged:
`check_indexes` now also reads each existing index's access method (`pg_am.amname`). When the method no longer matches what the field expects (`gin` for trigram, `btree` otherwise), the stale index is dropped and recreated. The drop is issued inside the **same savepoint** as the recreate, so a failed rebuild (e.g. a lock timeout) rolls the drop back and never leaves the column without an index.
Scope: only the access method is reconciled. A change that alters solely the partial predicate (`btree` -> `btree_not_null`) keeps the same method and is intentionally left untouched.
### Notes
- This extends the existing index-management logic in place and keeps the current "keep unexpected index" behaviour for fields that dropped `index=` entirely; only fields that still want an index, of a different method, are rebuilt.
- Trigram rebuilds still require the `pg_trgm` extension; without it the GIN index is skipped exactly as before (`self.has_trigram` guard).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271891
Forward-Port-Of: odoo/odoo#268505The stock forecast report now converts all move quantities into the same unit of measure as the product being viewed. This prevents the forecast graph from mixing grams and kilograms on the same chart, making quantities easier to read and avoiding misleading scaling.
Original PR description
When a stock move's UoM differs from the product template's UoM, the report aggregation incorrectly shows data for both UoMs of stock move.quantity on the same graph. All moves should be normalized…
When a stock move's UoM differs from the product template's UoM, the report aggregation incorrectly shows data for both UoMs of stock move.quantity on the same graph. All moves should be normalized to the UoM of the product for which we are viewing the forecast. We can do this with: `m.quantity * move_uom.factor / pt_uom.factor AS quantity` If the UoMs of the stock move and the product template are identical, as is the case most of the time, this simply multiplies by one, and the query behaves exactly as it did before. But if the units are distinct, the move UoM is converted into the product template UoM so that the data for stock move quantity is normalized to one shared unit across the entire forecast graph. **E.g.**: m.quantity == 500g m.UoM == g m.UoM.factor == 1 pt.UoM == kg pt.UoM.factor == 1000 500g * 1 / 1000 ==> .5kg **Steps to Reproduce on Runbot**: 1. Create a product which uses kg and g. 2. Confirm and Validate a receipt for this product (10 kg for example). 3. Confirm a second receipt for this product in the same UoM kg. 4. Confirm and Validate a delivery for this product with UoM g (500 g for example). 5. View the forecasted graph for the product, and you will see that the y axis is scaled on grams ~500, and the current / future stock moves in the report are still scaled based on kg. opw-6234066 Forward-Port-Of: odoo/odoo#266811
The embedded Mercado Pago payment form now uses the customer’s website language instead of always appearing in English. This makes checkout feel more consistent and easier to complete for customers in different regions.
Original PR description
The Mercado Pago Bricks SDK was always initialized with the `en-US` locale, so the embedded (inline) payment form rendered in English for every customer regardless of their website language. Resolve the Bricks locale from the website language instead. The locale is keyed by country, since each supported country maps to a single locale (e.g. Brazil is always pt-BR), so the language's country part is enough to resolve it. For the shared es_419 language, which carries no country, fall back on the company's country, and default to en-US for unsupported languages. task-6281783 Forward-Port-Of: odoo/odoo#269406
Vendor bills in foreign currencies are now matched against GST 2B amounts using the company’s base currency, which avoids false partial-match results. This prevents unnecessary reconciliation errors and makes GST reporting more reliable for businesses using multi-currency accounting.
Original PR description
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set…
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set an exchange rate. * Create a new vendor bill for an Indian vendor, setting the currency to USD. * Add lines to the bill and apply IGST/GST taxes, then confirm the bill. * Go to **Accounting → Reporting → GST Return Period** and initiate GSTR-2B matching for the period corresponding to the bill (using a valid JSON payload where the amounts are correctly reported in INR). **Observed behavior:** * The vendor bill is incorrectly marked as "Partially matched" instead of "Fully matched", accompanied by an exception stating that the total amount as per GSTR-2B does not match. **Cause:** * The GSTR-2B data fetched from the GST portal always reports values in the company's base currency (INR). * The `match_bills` method was directly comparing the GSTR-2B INR amounts ( `bill_total` and `bill_taxable_value`) against the bill's `amount_total` and `amount_untaxed` fields. * Because these fields return values in the document's foreign currency (e.g., USD), the mismatch triggers an exception and flags the bill as partially matched. **Fix:** * Modified the matching logic to compare GSTR-2B values against `abs(amount_total_signed)` and `abs(amount_untaxed_signed)`. * This ensures that the amounts evaluated during reconciliation are always correctly converted and compared in the company's base currency (INR). opw-6311097 Forward-Port-Of: odoo/enterprise#121677 Forward-Port-Of: odoo/enterprise#120967
This update prevents Colombian debit notes from failing when they are sent to DIAN. It removes an invoice reference field that is not supported in the debit note format, so the document can be generated and submitted correctly.
Original PR description
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on…
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on any database with DIAN and Colombian localization: 1. Create a new "Sales" type journal. Then, check the checkbox “Nota de Debito”. 2. Find a res.partner with a ref field, or add a ref field to any partner. 3. Make an invoice using the partner found in step 2. Ensure it uses a tax. Confirm it. 4. Send that invoice to DIAN. 5. Create a Debit Note for that invoice. Use the journal created in step 1. 6. Add a product, price, and tax to the debit note. Confirm it. 7. Send the debit note to DIAN. Explanation: The `_add_invoice_header_nodes` method on the AccountEdiXmlUbl_21 model adds a BuyerReference node unconditionally. (See account_edi_xml_ubl_21.py.) But the DebitNote XML template does not include a BuyerReference element (see ubl_21_debit_note.py). This caused a ValueError when assembling the XML for debit note documents. Solution: The fix overrides this in the Colombian localization by clearing the BuyerReference value when the document type is "debit_note". That way, the node is omitted from the output. opw-6181039 Forward-Port-Of: odoo/enterprise#121422
This update corrects a problem where new accounting tags weren't being properly applied during the setup process. Moving the tag remapping to occur after the database is loaded ensures all new tags are recognized, preventing errors and data inconsistencies. This improves the accuracy of Danish accounting records.
Original PR description
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent…
The tag remapping was running in pre-migrate, before the module's data files are loaded. This caused the tag swap to be silently skipped for any new tag that didn't exist yet, and the subsequent cleanup to fail with a FK violation on account_account_account_tag.
```py
File "/home/odoo/src/odoo/saas-19.2/odoo/sql_db.py", line 417, in execute
self._obj.execute(query, params)
psycopg2.errors.ForeignKeyViolation: update or delete on table "account_account_tag" violates foreign key constraint "account_account_account_tag_account_account_tag_id_fkey" on table "account_account_account_tag"
DETAIL: Key (id)=(356) is still referenced from table "account_account_account_tag".
```
Moving to post-migrate ensures all new account tags are present in the database before the remapping and cleanup run.
upg-[4341331]
[4341331]: https://upgrade.odoo.com/odoo/upgrade.request/4341331?debug=1
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#269809This update resolves an issue where Purchase Orders incorrectly appeared in the 'Late Receipts' filter after a backorder was cancelled. The fix ensures that cancelled backorders are no longer considered as pending receipts, accurately reflecting the status of the purchase order. This improves the accuracy of the 'Late Receipts' report.
Original PR description
Steps to reproduce: ------------------- - Create a Purchase Order with an expected Arrival date in the past - Confirm the Purchase Order - Validate the receipt partially and create a backorder -…
Steps to reproduce: ------------------- - Create a Purchase Order with an expected Arrival date in the past - Confirm the Purchase Order - Validate the receipt partially and create a backorder - Cancel the generated backorder - Open the Purchase Orders list and check the 'Late Receipts' Issue: ------ The Purchase Order still appears in the 'Late Receipts' filter even though there is no remaining receipt to process. Cause: ------ The 'Late Receipts' filter relies on the computed search field `is_late`: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase/views/purchase_views.xml#L439 The search domain for this field is generated by `purchase.order._search_is_late()`: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase/models/purchase_order.py#L176 In `purchase_stock`, `_get_domain_is_late()` extends the base domain to identify Purchase Orders that still have receipts pending: https://github.com/odoo/odoo/blob/324df67c099ab18c6fe7c8f77212cf809debf383/addons/purchase_stock/models/purchase_order.py#L264-L267 After a partial receipt: - the original receipt is in state `done`, - a backorder is created and linked to the Purchase Order, - the backorder is later cancelled and moves to state `cancel`, - the Purchase Order line still has `qty_received < product_qty`. The existing domain excludes only `done` pickings when determining whether a receipt is still pending. As a result, a cancelled backorder is still treated as an unfinished receipt, causing the Purchase Order to remain visible in the 'Late Receipts' filter. Fix: ---- Exclude both `done` and `cancel` pickings when determining whether a Purchase Order has pending receipts. A cancelled backorder indicates that the remaining quantity will not be received through that transfer. Therefore, once all related pickings are either completed or cancelled, the Purchase Order should no longer be considered late. --- opw-6266046 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268488
This pull request resolves several test failures related to the Blackbox POS integration for Belgium. It corrects issues with test setup, data loading, and order synchronization, ensuring accurate reporting and functionality. The changes improve the reliability of the Blackbox tests and the overall POS system.
Original PR description
1. The `m160` and `m161` mutations for `sign_copy_sale` test didn't set the `l10n_be_short_signature` field on the order, so the `TicketScreen.print` override would fail the check and the…
1. The `m160` and `m161` mutations for `sign_copy_sale` test didn't set the `l10n_be_short_signature` field on the order, so the `TicketScreen.print` override would fail the check and the `blackbox.signCopy` would not be called, causing the test to fail. 2. The `l10n_be_pos_blackbox_urban_piper` tests would crash on `undefined id` on the prep display path of `pos_enterprise`, where the data service will try to load up the prep display data, but it's not loaded in the test bundle. So I created a special setupEnv method for blackbox with urban piper which unpatches the prep display (same mechanism as pos_enterprise) 3. After removing the path for the tests, they would fail for the `expectGeneralProperties` step. By default it expects the `ticketMedium` to be `PAPER`, but there is no printer configured on the tests, so the actual medium is `DIGITAL`. 4. The tests expect the cost center to be `PLATFORM`. There was a patch on `InputGenerator`, which would return platform if the order has a `delivery_provider_id` set. But the patch never fired. I moved the patch directly on the order model, which is where the cost center value is computed. 5. The `test_l10n_be_pos_blackbox_sign_sale_backend_offline` test would endTour prematurely before the orders finished syncing, then check that all the orders are synced. I added an extra isSynced() step to ensure the orders are synced before ending the tour Task-[6320705](https://www.odoo.com/odoo/1737/tasks/6320705) Forward-Port-Of: odoo/enterprise#121455
2 changes
Resolved issues and error corrections
This update resolves an issue where vendor bills in foreign currencies (like USD) were incorrectly flagged as 'Partially matched' during GSTR-2B reporting. The fix ensures that amounts are correctly converted to the company's base currency (INR) for accurate reconciliation, preventing reporting errors.
Original PR description
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set…
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set an exchange rate. * Create a new vendor bill for an Indian vendor, setting the currency to USD. * Add lines to the bill and apply IGST/GST taxes, then confirm the bill. * Go to **Accounting → Reporting → GST Return Period** and initiate GSTR-2B matching for the period corresponding to the bill (using a valid JSON payload where the amounts are correctly reported in INR). **Observed behavior:** * The vendor bill is incorrectly marked as "Partially matched" instead of "Fully matched", accompanied by an exception stating that the total amount as per GSTR-2B does not match. **Cause:** * The GSTR-2B data fetched from the GST portal always reports values in the company's base currency (INR). * The `match_bills` method was directly comparing the GSTR-2B INR amounts ( `bill_total` and `bill_taxable_value`) against the bill's `amount_total` and `amount_untaxed` fields. * Because these fields return values in the document's foreign currency (e.g., USD), the mismatch triggers an exception and flags the bill as partially matched. **Fix:** * Modified the matching logic to compare GSTR-2B values against `abs(amount_total_signed)` and `abs(amount_untaxed_signed)`. * This ensures that the amounts evaluated during reconciliation are always correctly converted and compared in the company's base currency (INR). opw-6311097 Forward-Port-Of: odoo/enterprise#121563 Forward-Port-Of: odoo/enterprise#120967
This update resolves an issue where quality checks remained active after merging multiple Manufacturing Orders. Previously, the merge process didn't trigger the standard cleanup, leading to lingering quality check entries. Now, when Manufacturing Orders are merged, pending quality checks are correctly deleted, and the 'Quality Checks' button disappears.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous fix introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: odoo-dev@db93bd2 This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L2480 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- opw-6260735 Forward-Port-Of: odoo/enterprise#121536 Forward-Port-Of: odoo/enterprise#119525
8 changes
Resolved issues and error corrections
This fix prevents an error that could block Point of Sale session closing when a default tax is configured on the cash difference gain account. The cash difference amount is now split correctly so the closing entry stays valid and can be posted without manual correction.
Original PR description
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session,…
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session, count more cash than expected at closing. 3. Try to close the session. -> Error message shows up "The journal entry reached an invalid state..." ... "The journal entry must always have exactly one journal item involving the bank/cash account" What's happening ---------------- PoS creates a bank statement line with the gain account as counterpart, resulting in 2 lines: cash +10, gain -10. Since the gain account has a default tax, `_sync_tax_lines` adds a tax line of -2.5 on top, which makes the move unbalanced by 2.5. Then `_sync_unbalanced_lines` adds a 4th line to fix it, on the line returned by `_get_automatic_balancing_account`, which is `journal.default_account_id`, i.e. the cash account itself for a cash journal. So we end up with 2 lines on that same cash account, which a bank statement line move doesn't allow -> Error. The fix ------- In `_post_statement_difference`, precompute the base and tax split ourselves and build the statement line's `line_ids` directly (e.g. for +10 and a 25% tax: cash +10, gain -8, tax -2). The move is balanced from creation, so `_sync_tax_lines` and `_sync_unbalanced_lines` don't have to touch it. Note that we force the tax computation to be in 'force_price_include' mode, as the counted cash difference is a gross amount (physical money in the drawer). This way the tax is always extracted from the cash amount, regardless of how the tax is configured (included or excluded in price). Same pattern is already used by `hr_expense` (cf `hr_expense.models.account_move_line._compute_totals`). opw-5972690 Forward-Port-Of: odoo/odoo#270344 Forward-Port-Of: odoo/odoo#257892
This change fixes a problem where importing certain valid UBL invoices could fail with a division-by-zero error. Empty lines with no quantity and no amount are now skipped automatically, so the invoice import completes without showing an error in the chatter.
Original PR description
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an…
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an import error Such lines are valid UBL but carry no meaningful value, so they are silently skipped after the fix ### Cause: After this commit: https://github.com/odoo/odoo/commit/a7f77f3cfc42764328e7da73a60df8d4cafc968f The `line_extension_amount` was able to go in new parts of the code with a 0.0 value When `line_extension_amount` is set and `invoiced_quantity` is 0, `quantity` is computed as `subtotal * price_quantity / (...)` which resolves to 0 since `subtotal` is also 0 `price_unit = subtotal / quantity` then divides by zero ### Steps to reproduce: - Install `l10n_be` - Import a UBL invoice with a line where `LineExtensionAmount=0`, `InvoicedQuantity=0` and `PriceAmount` is non-zero (You can use the xml on the ticket) Before the fix, the import failed with an error in the chatter opw-6234453 Forward-Port-Of: odoo/odoo#271001
This fix prevents a crash when users open a billing target from the Timesheets configuration. It ensures the page can display the needed presence and leave information even for users who do not have Employee access, so the workflow stays uninterrupted.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` and `current_leave_id` field, change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value.
This change fixes a performance issue in the rich text editor when working with very large documents. It prevents the page from freezing or showing an error by handling large content more efficiently, which makes editing more reliable and responsive.
Original PR description
For complex content, descendants(root) can return more than 100K elements. Using the spread operator expands all descendants into individual function arguments, which may exceed the JavaScript's argument limit and trigger a "Maximum call stack size exceeded" error. Replace with push() each node to the targetNodes. ||Before|After| |-|-|-| |getTargetNodes|Page Unresponsive|585 ms| Related ticket: opw-6303814 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271250
The default accounts used for cash discounts in the German SKR03 chart of accounts were pointing to the wrong codes. This update corrects those defaults so businesses using this localization will have the right accounts set automatically.
Original PR description
The default cash discout accounts referenced in the
German skr03 template used the wrong account codes.
The template has been updated with the right ones.
task-4915939
opw-4909059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#271383
Forward-Port-Of: odoo/odoo#271024The default account codes used for cash discounts in the German SKR03 template have been corrected. This helps ensure accounting entries are mapped to the proper accounts and reduces the risk of reporting or posting errors.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121406 Forward-Port-Of: odoo/enterprise#121180
Fixed an issue where previewing a webhook sample payload could fail when a selected field returned complex data structures. The preview now converts these values safely, so users can view the payload without an error.
Original PR description
**Steps to Reproduce:** - Create a Server Action of type 'Webhook Notification'. - Select a model containing a field that returns a `frozendict`-based structure (e.g. `account.move` →…
**Steps to Reproduce:** - Create a Server Action of type 'Webhook Notification'. - Select a model containing a field that returns a `frozendict`-based structure (e.g. `account.move` → `needed_terms`). - Add the field to the webhook fields. - Open the webhook sample payload preview. **Issue:** - During sample payload generation: - The selected fields are read from a sample record. - A selected field returns a structure containing `frozendict` objects. - The payload is serialized using `json.dumps()`. - JSON serialization fails with: ```text TypeError: keys must be str, int, float, bool or None, not frozendict ``` - The webhook sample payload computation crashes and the preview cannot be displayed. **Root Cause:** - The webhook sample payload may contain `frozendict` objects returned by selected fields. - The serializer used for payload generation does not handle such mapping-like objects, causing `json.dumps()` to fail. **Solution:** - Use a serializer that converts mapping-like objects into JSON-compatible structures before serializing the webhook sample payload. **OPW-6295777** Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects a bug where quality checks remained active after merging multiple Manufacturing Orders. Previously, the merge process didn't trigger the standard cleanup of these checks. Now, when MOs are merged, pending quality checks are automatically removed, preventing unnecessary clutter and ensuring data accuracy. This improves the user experience and streamlines the manufacturing workflow.
Original PR description
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that…
Version: -------- - 18.0+ Steps to reproduce: ------------------- - Install `quality_mrp` - Create a manufactured product with a BoM - Create a Quality Point for the `Manufacturing` operation of that product - Create and confirm multiple Manufacturing Orders - Verify that each MO generates a quality check - From the MO list view, select the MOs and merge them from the gear menu(merge) Issue: ------ When Manufacturing Orders are merged, All MOs are cancelled but it keep their quality checks in the 'To Do' state. As a result: - The quality checks remain linked to cancelled MOs - The 'Quality Checks' smart button is still displayed on cancelled MOs Expected behavior: ------------------ - Pending quality checks should be deleted when the MO is cancelled - The 'Quality Checks' smart button should no longer be displayed Cause: ------ A previous fix introduced logic to remove pending quality checks when a Manufacturing Order is cancelled: odoo-dev@db93bd2 This logic was implemented in `action_cancel()` by unlinking quality checks associated with the cancelled MO: https://github.com/odoo/enterprise/blob/20bc0eb5c2cec67eecd3b44450934e23370b48f2/quality_mrp/models/mrp_production.py#L94-L97 However, when MOs are merged, the merge flow does not call `action_cancel()`. Instead, it directly invokes `_action_cancel()` on the source Manufacturing Orders: https://github.com/odoo/odoo/blob/aca0b7289c68fc7a75d47ab313f5f791ebf30f7d/addons/mrp/models/mrp_production.py#L2480 Since the quality check cleanup is implemented only in `action_cancel()`, it is bypassed during the merge process. As a result, the source MOs are cancelled but their pending quality checks remain in place. --- opw-6260735 Forward-Port-Of: odoo/enterprise#121536 Forward-Port-Of: odoo/enterprise#119525
2 changes
Resolved issues and error corrections
Selling a combo in Kenyan PoS no longer triggers an eTIMS registration warning for the combo itself. Only the actual products inside the combo are treated as items to register, so checkout can be completed normally when the combo parent item is not registered.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#119362
The default account codes used for cash discounts in the German SKR03 setup were incorrect and have been updated. This helps ensure accounting exports and defaults use the right accounts, reducing the risk of misposted transactions.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121406 Forward-Port-Of: odoo/enterprise#121180
11 changes
Resolved issues and error corrections
This change removes an unintended extra padding in the bank reconciliation widget. It makes the layout look more consistent and improves the display of statement lines for users working in accounting.
Original PR description
Since this commit: https://github.com/odoo/odoo/commit/185b70434091d7c20b3993d59dad6490a8a77a6e it seems that kanban record have an extra padding to it. This pr will remove it in the bank rec widget at least. no task id
When users switch the Gantt timeline between day, week, month, or year views, the chart now stays centered on the same point they were looking at instead of jumping back to today. This makes it easier to continue planning or reviewing work without losing context.
Original PR description
*: project_enterprise This commit ensures that switching the Gantt view scale (day, week, month, year) anchors the new time period around the date currently centered in the viewport, rather than defaulting back to "today". Two coordinated changes make this possible: * **Range Selection:** `selectRangeId` now passes `getCurrentFocusDate()` (the pixel-computed center of the viewport) to `getRangeFromDate` instead of defaulting to `DateTime.now()`. * **Viewport Scrolling:** `focusDate` has been refactored to scroll the targeted date directly to the center of the viewport rather than its left edge. This is achieved by subtracting half the visible cell area width from the computed scroll position. The focusGroup behavior is removed since it is obsolete due to the fact that the default period only shows 1 group instead of 3. task-6314686
This change updates how automated tests clean up test components so they remove whole test apps only when appropriate. It prevents tests from accidentally tearing down shared pieces of the interface, which makes the test suite more stable and reduces flaky failures.
Original PR description
- Community: https://github.com/odoo/odoo/pull/271765 Before this commit, 'destroy' was used to destroy individual components in unit tests. The issue is that this helper is meant to destroy the entire app, which creates weird situations when several components are spawned under the same app in a same test. This commit ensures the 2 following scenarios: - the previous component is entirely replaced, and 'destroy' is used legitimately; - or multiple components have been aggregated under a common parent, and are then mounted/unmounted through reactivity.
This update resolves a stability issue in the Gantt chart module. Enabling user chatter previously caused test crashes due to missing data. This commit adds the necessary model changes to ensure compatibility and reliable operation.
Original PR description
Enabling user chatter caused crashes in tests because the mock user model was missing expected fields. This commit adds the necessary model inheritances to provide those fields. **Community PR:** odoo/odoo#265502 **Task**: 4933086
This update streamlines the layout of quantity buttons within the Odoo inventory barcode interface. Previously, a confusing button arrangement and inconsistent delete functionality caused user friction. Now, the layout is more intuitive, and the delete button's behavior has been clarified to only remove lines from the view, improving the user experience.
Original PR description
This commit improves the layout of quantity buttons in barcode in both cases of physical inventory and transfers. ### Before this commit: 1- The fulfill button disappeared if `quantity done == demand…
This commit improves the layout of quantity buttons in barcode in both cases of physical inventory and transfers. ### Before this commit: 1- The fulfill button disappeared if `quantity done == demand - 1` which causes the increment and decrement buttons to shift their positions, that caused confusion to the user. 2- The delete button (red trash button) in case of physical inventory count was used to set the count of the product to 0 and remove the line from barcode view. 3- The "?" button (to mark the quantity as not set yet while inventory count) appeared whether the quantity on line was set to a number >= 0. 4- The button for registering components was among the lower buttons (increment, decrement, and fulfill). ### After this commit: 1- The fulfill button still disappears when `quantity done == demand - 1` but an empty spacer replaces it, which causes other buttons to hold positions. 2- The delete button now only appears when the user adds a product by themselves using the form or scanning the product (not while the product is in an inventory request). Also the functionality is of the button is now different, it just removes the line from the barcode view without affecting the inventory count at all. 3- The "?" button now only appears if the quantity = 0. 4- The button for registering components is no next to the edit button. Upgrade PR: https://github.com/odoo/upgrade/pull/10224 Task-6095725
This update resolves an issue where the website link wasn't correctly populated when creating a lead through the AI-powered CRM tool. The fix ensures that the visitor's website information is accurately captured, improving the lead generation process. This prevents missing website data from being associated with new leads.
Original PR description
see: https://github.com/odoo/odoo/pull/252766 ERROR: Subtest TestAiCrmLivechatTools.test_create_lead_tool_from_livechat (login='public_user') Traceback (most recent call last): File…
see: https://github.com/odoo/odoo/pull/252766
ERROR: Subtest TestAiCrmLivechatTools.test_create_lead_tool_from_livechat (login='public_user') Traceback (most recent call last):
File "/data/build/odoo/odoo/tools/safe_eval/evaluation.py", line 431, in safe_eval
return unsafe_eval(c, globals_dict, None)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "ir.actions.server(272,)", line 1, in <module>
File "/data/build/odoo/odoo/tools/safe_eval/runtime.py", line 659, in safe_call
return callee(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/ai_crm/models/crm_lead.py", line 16, in _ai_create_lead
self.create(self._ai_prepare_lead_creation_values({
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/ai_crm_livechat/models/crm_lead.py", line 21, in _ai_prepare_lead_creation_values
if 'website' in self.env and (visitor := channel.livechat_visitor_id):
^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'discuss.channel' object has no attribute 'livechat_visitor_id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/build/odoo/odoo/tests/common.py", line 2949, in with_users
func(self, *args, **kwargs)
File "/data/build/enterprise/ai_crm_livechat/tests/test_ai_crm_livechat_tools.py", line 17, in test_create_lead_tool_from_livechat
tool.with_context({'discuss_channel': livechat_channel})._ai_tool_run(None, {
File "/data/build/enterprise/ai/models/ir_actions_server.py", line 288, in _ai_tool_run
self._run_action_code_multi(eval_context=eval_context)
File "/data/build/odoo/odoo/addons/base/models/ir_actions.py", line 1012, in _run_action_code_multi
safe_eval(self.code.strip(), eval_context, mode="exec", filename=str(self))
File "/data/build/odoo/odoo/tools/safe_eval/evaluation.py", line 437, in safe_eval
raise ValueError('%r while evaluating\n%r' % (e, expr))
ValueError: AttributeError("'discuss.channel' object has no attribute 'livechat_visitor_id'") while evaluating "ai['result'] = record.sudo()._ai_create_lead(name, contact_name, description, email, phone, team_id, tag_ids, priority, country_id, state_id, city, zip_code, street, job_position)"This update resolves an issue where users assigned to sign requests ('Own Templates' group) were encountering an 'Access Error' when attempting to sign documents. The fix utilizes `sudo()` to correctly access document counts, ensuring these users have the necessary permissions to open and sign documents. This improves the user experience for sign requests created with the 'Own Templates' access right.
Original PR description
Steps to Reproduce: 1. create a new user (UserB) and grant the 'User: Own Templates' access right. 2. send a new Sign Request to UserB. 3. log in with the UserB account and try to sign the document. Issue: An 'Access Error' message is displayed instead of opening the document to sign. Cause: `go_to_document` and `go_to_signable_document` read `self.template_id.document_ids` to compute `document_count`, and the `sign.template` record rule for `group_sign_user` only grants access to the template owner. Users assigned to sign request created from that template do not have access to the template itself, so reading `document_ids` raises an `AccessError` before the document can be opened. Solution: Used `sudo()` in both methods to compute document_count.
This update resolves an issue preventing proper grouping in the resource search view based on job position. The fix ensures that users can now filter and group resources accurately, improving search efficiency. This enhancement streamlines resource management within the Enterprise module.
Original PR description
In a recent commit, we added the job position to the resource search view. However, the group by was not working because the field was not stored. This is now fixed in this commit. task-6329358
A previous bug caused an unwanted 'Uninstall modules' prompt to appear after saving settings, specifically when the Website Form module was installed. This fix ensures the module remains installed regardless of the Website Form setting, as it's now essential for displaying Field Service information in the portal. This prevents unnecessary user disruption.
Original PR description
Steps to reproduce: - 1. Install `website` and `planning_field_service` (so `website_planning_field_service` auto-installs). 2. Open Settings and click Save. Issue: - An "Uninstall modules" wizard…
Steps to reproduce: - 1. Install `website` and `planning_field_service` (so `website_planning_field_service` auto-installs). 2. Open Settings and click Save. Issue: - An "Uninstall modules" wizard pops up offering to remove `website_planning_field_service`. Cause: - Since the module is now `auto_install` with its `post_init_hook` removed, it is installed alongside `website` and `planning_field_service` while the setting remains disabled by default. On Save, `set_values` re-derives the `module_website_planning_field_service` field from a company `search_count`, setting it to False when no company has the feature enabled, even though the module is installed. Base `execute()` then sees `module_* = False` on an installed module and re-offers the uninstalls. Fix: - Make `set_values` install-only: enabling the setting still installs the module, but disabling it no longer attempts to uninstall it. The module is now also used to show or hide Field Service information in the portal, so it must remain installed even when the Website Form feature is disabled. task-6330718
This update resolves issues where AI record creation and updates were failing due to missing history data, leading to blank responses for users. Additionally, the system was incorrectly duplicating AI search filters during record reloads. The fix ensures AI history is properly captured and filters are applied only once, improving the reliability and performance of AI-powered record operations.
Original PR description
## Issue Pending tool results were missing from history we read for create/update, potentially producing empty responses. Also the create/ update soft reload actions are duplicating the AI search filters in the records' search view if the view is already open and filters are already set. ## Fix Refresh the session history after pending tool calls and avoid reapplying AI search criteria when restoring existing search state. task-id-6329071
This update fixes an issue where shift report PDFs displayed unnecessarily large pills for single-line shift names. The change ensures shift pill sizes are now correctly optimized for single-line names while still accommodating longer names that wrap to multiple lines. This improves the visual clarity and consistency of shift reports.
Original PR description
### Steps to reproduce: 1. Go to Planning. 2. Create a shift with a short name that easily fits on a single line. 3. Click Actions > Print to generate the PDF report. 4. Observe the printed shift pill. ### Issue: Single-line shift pills look unusually large because they take up unnecessary vertical space on the printed report. ### After: The pill now correctly shrinks to fit a single-line name natively, while still expanding downward if a longer name wraps to a second line. task-5062148
5 changes
Resolved issues and error corrections
This change prevents in-page anchor links in emails from being converted into tracking redirects. As a result, links like "#section" keep working correctly when recipients open the final sent message, instead of sending them to the website home page.
Original PR description
When a mailing is sent, its body is run through _shorten_links to turn links into /r/ tracking URLs. find_links_with_urls_and_labels in addons/link_tracker/tools/html.py prepends the base URL to any…
When a mailing is sent, its body is run through _shorten_links to turn links into /r/ tracking URLs. find_links_with_urls_and_labels in addons/link_tracker/tools/html.py prepends the base URL to any href starting with /, ? or #, so a fragment only anchor such as #section becomes http://host#section and is shortened into a tracking link. A recipient clicking it lands on the website home instead of the section, so the in-page navigation inside the email no longer works. Send Test does not shorten links, so the anchor still works when sending a test. Only the real send shortens links, which is why the anchor works in the test but breaks once the mailing is actually sent. link.tracker.create already refuses URLs starting with ? or # because they point to the current page, but prepending the base URL first turns them into absolute URLs that get past that check. https://github.com/odoo/odoo/blob/deeecf7cd02e/addons/link_tracker/models/link_tracker.py#L181-L182 find_links_with_urls_and_labels now skips hrefs starting with # or ?, the same set link.tracker.create rejects, so only paths starting with / are made absolute and tracked. The check sits in the shared helper so every caller of the shortener gets it. Anchor links are left as written. Steps to reproduce: 1. Open Email Marketing and create a mailing, set its recipients to a list containing your own address. 2. Add a button in the body, open its link options and set the URL to #section. 3. Send the mailing. 4. Open the received email and check the button link. => the anchor is a /r/ tracking link that redirects to the website home instead of the section Ticket [link](https://www.odoo.com/odoo/project.task/6310081) opw-6310081
Importing certain valid UBL invoice lines with zero quantity and zero value will no longer fail. These empty lines are now skipped automatically, which prevents the invoice import from stopping with an error message.
Original PR description
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an…
### Issue: Importing a UBL invoice containing a line with `LineExtensionAmount=0`, `InvoicedQuantity=0` and a non-zero `PriceAmount` failed with a `ZeroDivisionError`, reported in the chatter as an import error Such lines are valid UBL but carry no meaningful value, so they are silently skipped after the fix ### Cause: After this commit: https://github.com/odoo/odoo/commit/a7f77f3cfc42764328e7da73a60df8d4cafc968f The `line_extension_amount` was able to go in new parts of the code with a 0.0 value When `line_extension_amount` is set and `invoiced_quantity` is 0, `quantity` is computed as `subtotal * price_quantity / (...)` which resolves to 0 since `subtotal` is also 0 `price_unit = subtotal / quantity` then divides by zero ### Steps to reproduce: - Install `l10n_be` - Import a UBL invoice with a line where `LineExtensionAmount=0`, `InvoicedQuantity=0` and `PriceAmount` is non-zero (You can use the xml on the ticket) Before the fix, the import failed with an error in the chatter opw-6234453
This update corrects a test case that used an invalid Belgian VAT number, which started failing after a stricter validation update in a supporting library. The test still checks for a VAT mismatch, but now uses a valid VAT number so it remains reliable across environments.
Original PR description
This commit fixes a Belgian VAT validation check in `test_import_partner_retrieval_bank_account_number` as the provided vat number isn't a valid one. It keeps the spirit of the test by still having vat number mismatch, but with a valid value. The python-stdnum library used for this validation added a stricter check since version 2.2, which is used in Ubuntu Resolute 26.04. References: - https://github.com/arthurdejong/python-stdnum/commit/7ca9b6ce7b1f2b4d1bf164c2af83a8a77bc919d2 runbot-939796
Confirmed purchase orders now let users edit the line description consistently, even when the product column is visible. This fixes an inconsistency that previously blocked edits in one view but not another, improving day-to-day purchase order handling.
Original PR description
Steps to reproduce the bug: - Create and Confirm a purchase order with any product and a description (name) on the order line - Try to edit the description (name) field Problem: The description field…
Steps to reproduce the bug:
- Create and Confirm a purchase order with any product and a description (name) on the order line
- Try to edit the description (name) field
Problem:
The description field was not editable on a confirmed purchase order when the product_id column was visible, but became editable when product_id was hidden.
The `ProductLabelSectionAndNoteField` widget renders both `product_id` and the description (`name`) in a single cell. When `props.readonly` is true (because `product_id` has `readonly="state in ('purchase', 'to approve', 'done', 'cancel')"`) and the order state is not draft (`isProductClickable` is true), the template rendered the description textarea with a hardcoded `readonly="1"` attribute, making it impossible to edit regardless of the actual intended readonly state for the description.
When `product_id` was column-invisible, the `name` field rendered via its own `section_and_note_text` widget, which correctly used `sectionAndNoteIsReadonly` (blocking only `cancel`, `done`, `posted`) hence the inconsistency.
Solution:
Replace `readonly="1"` with `t-att-readonly="sectionAndNoteIsReadonly"` on the description textarea so its editability follows the same logic as the other cases: blocked only for terminal states (`cancel`, `done`, `posted`), not for `purchase` or `to approve`.
opw-5474986The GSTR-1 spreadsheet now reports the invoice value for SEZ invoices in Indian Rupees instead of the foreign invoice currency. This makes the export consistent with company currency and avoids incorrect return figures.
Original PR description
Currently, when generatign GSTR-1 return spreadshee, SEZ invoices issued in a foreign currency are exported with their totals in the foreign currency rather than the company currency (INR) Steps to reproduce: - Create a B2B SEZ invoice in foreign currency - Go to Accounting > Reporting > [India] GST Return periods - Generate the GSTR-1 report for the period Issue: In the resulting spreadsheet, the "Invoice Value" column takes the invoice total in USD rather then INR opw-6292913 Forward-Port-Of: odoo/enterprise#121157
2 changes
Resolved issues and error corrections
This update adjusts how manufacturing work order time is calculated so all time loss types are kept in the total. It helps avoid confusing or incomplete time tracking in cases where delays or interruptions were previously left out.
Original PR description
This commit amend this previous fix 08ef4947fe2e3edb990b544a9b9c67c861d3b01b that make the duration of workorder time respect the overlaps. However we decided to exclude some time loss types in the computation. This will surely broke some cases and can be misunderstood. This will be reworked correctly later. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix adds validation to the Company SIA Code so it must be exactly 5 characters for Italian Ri.Ba. exports. This prevents batch payment validation from failing with an error when the code is entered with the wrong length.
Original PR description
Currently, the sia_code field on res.company lacks length validation. For Italian Ri.Ba (CBI) exports, this field MUST be exactly 5 characters. If a user enters more (e.g., during initial setup), the Batch Payment validation (specifically the XML file generation) crashes with a traceback. Steps to Reproduce: - Set Company SIA Code to 6+ characters - Create multiple payments with Ri.Ba. method - Create a Ri.Ba Batch Payment - Click 'Validate' Ticket [link](https://www.odoo.com/odoo/project.task/6031062) opw-6031062