Daily updates from Odoo
Wednesday, July 8, 2026
439 changes
23 changes
Enhancements to existing features
The Azerbaijani Manat currency symbol has been updated to its official Unicode character, ₼. This improves consistency and makes currency display more accurate for users working with AZN.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
The forum editor toolbar has been simplified by removing options that are not needed in that context, and its styling has been adjusted to stay consistent with the forum design. This update also fixes an issue that could cause errors when opening table editing tools, improving the editor’s reliability for forum users.
Original PR description
Description of the feature this PR addresses: - Remove unwanted toolbar features (heading, font_family, powerbuttons, undo/redo buttons) - Update toolbar styles in website_forum to keep them consistent - Fix table menu traceback by passing missing `localOverlayContainers` in `website_forum_wysiwyg` config task-6123698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274139 Forward-Port-Of: odoo/odoo#263326
This change speeds up the creation of backorders when validating receipts with many operations. It reduces processing time and avoids database memory errors, so large warehouse receipts are much less likely to time out.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667 Forward-Port-Of: odoo/odoo#273555 Forward-Port-Of: odoo/odoo#269350
This change makes the tax supply date available for German accounting documents. It helps businesses record taxes more accurately according to the relevant supply date, improving compliance and consistency in tax reporting.
Original PR description
Forward-Port-Of: odoo/odoo#272461
This update refreshes the web editing engine to the latest Owl version used by Odoo. It helps keep the platform aligned with the newest underlying framework changes and avoids issues caused by internal API changes in the editor.
Original PR description
Release notes: https://github.com/odoo/owl/releases/tag/v3.0.0-alpha.42 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Fixed an error that could appear in Live Chat when a chatbot tries to transfer a visitor to an operator but none are configured. Instead of crashing the conversation, the system now handles this case safely so the chat can continue without an interruption.
Original PR description
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install…
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install ``im_livechat`` module with demo data - Go to Live Chat > Configuration > Chatbots > Create a new chatbot > Add script > Step Type: Question > Set answers > Save > Add script > Step Type: Forward to operator > Only If: Set one of the above answers > Save - Go to Live chat > Channel > Click the configure channel on YourWebsite.com > Remove the operators > Save - Go to the chatbot > test > select the configured answer Traceback: ```py StopIteration ``` https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/im_livechat/controllers/chatbot.py#L65-L70 When the chatbot script reaches a Forward to operator step while no operator is configured in the live chat channel, no chatbot message is created. As a result, the generator iterates over an empty iterator, and the ``next()`` call raises a ``StopIteration`` exception, causing a traceback during the conversation. sentry-7435424405 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274615 Forward-Port-Of: odoo/odoo#261726
The Point of Sale screen now shows the change due to the customer with the correct sign and amount. This fixes cases where refunds or overpayments could display misleading values, helping staff clearly see what should be returned.
Original PR description
Steps to Reproduce ------------------------ - Install point of sale. - Do a order and pay more than the amount. Issue ------ - The change amount is displayed as a positive value on the UI. - Typically, amounts going out of the shop (like change given to the customer) should be shown as negative. Cause ------- - The change amount was not correctly represented in the UI. - Since the change flows in the opposite direction of the payment, it should be displayed as the negation of the original amount. FIX ----- - Updated the frontend to display the change amount with the correct (negative) sign. - No backend changes were required, as the correct value was already being handled during order synchronization Enterprise PR: https://github.com/odoo/enterprise/pull/112560 task: 6074620 Forward-Port-Of: odoo/odoo#274534 Forward-Port-Of: odoo/odoo#256776
This change updates a payment-related test to use a smaller, more targeted XML sample instead of generating a full XML file. It helps make the test more reliable and easier to maintain, reducing the chance of false failures in invoice import checks.
Original PR description
Move the partner retrieval bank account number test to the `test_ubl_import_bis3_invoice_be_retrieve_partner.py` file and use a partial XML instead of a generated XML. Forward-Port-Of: odoo/odoo#274591 Forward-Port-Of: odoo/odoo#269995
This update fixes several issues in the emoji editor so selected emojis replace typed text properly and mobile backspace behaves as expected. It improves the editing experience by keeping the cursor in the right place and preventing emojis from reappearing after deletion on mobile devices.
Original PR description
**Issue 1:** Step to reproduce: - Type ':wave' to open suggestion list - Now click on any emoji from the suggestion list Description of the issue: - The selected emoji gets inserted, but the…
**Issue 1:** Step to reproduce: - Type ':wave' to open suggestion list - Now click on any emoji from the suggestion list Description of the issue: - The selected emoji gets inserted, but the `searchNode` `:wave` does not get removed and remains beside the inserted emoji Cause: - When the user clicks an emoji from the suggestion list, focus shifts to the suggestion list item. As a result, `selection.extend()` is unable to properly select the searchNode in the editable area. Because the `searchNode` is not selected, `deleteSelection()` fails to remove it before inserting the emoji. Solution: - Added the `user-select-none` class to the suggestion list to prevent selection/focus shift on emoji click, ensuring the searchNode is properly selected and replaced by the selected emoji **Issue 2:** Steps to reproduce: - Open a To-do on a mobile device. - Type `:p` to create an emoji. - Press Backspace. Issue: - When using the SwiftKey keyboard, pressing Backspace after an emoji can result in an incorrect cursor position. Cause: - When Backspace is pressed, a selection snapshot is cached during the `keydown` event. - Later, `deleteBackward` converts the emoji back to its corresponding expression (:p) by triggering an undo operation, but the cached selection does not get updated. As a result, the previously cached selection is reused, causing the cursor to be placed incorrectly. Solution: - After performing the undo, update the cached selection to match the new cursor position. - This ensures that the latest selection is used instead of the outdated selection captured during `keydown`. **Issue 3:** Steps to reproduce: - Open a To-do on a mobile device. - Type `:p` to create an emoji. - Press Backspace. Issue: - Pressing Backspace on an emoji does not revert it to its matching expression (`:p`). Cause: - On mobile devices, `event.key` can be undefined in keydown. As a result, `deleteBackward` is triggered through the `beforeinput` event, which correctly reverts the emoji to its matching expression. However, after that, the `input` event is triggered and converts the expression back into the emoji again, making it appear as if the emoji was not reverted. Solution: - When the event type is `deleteContentBackward`, skip converting the expression back into an emoji and return early. task-6201173 Forward-Port-Of: odoo/odoo#272565 Forward-Port-Of: odoo/odoo#263777
The display of the Pakistan Rupee (PKR) has been updated so the currency symbol appears before the amount, matching local market practice. This helps make invoices and financial documents look more familiar and accurate for users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
Invoices sent through Nilvera could get stuck in a temporary “Unknown” state and stop being checked again. This change keeps those invoices in the follow-up process until Nilvera returns a final status, reducing cases where invoice processing appears stuck.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311Customers paying through DPO will now be sent to the payment page successfully instead of reaching an invalid transaction error page. The fix preserves the payment token in the URL during the redirect, which prevents the payment flow from breaking and restores normal checkout behavior.
Original PR description
When a customer paid through DPO, they landed on the DPO error page ("Not Valid - this transaction is no longer valid") instead of the payment page, even though the transaction token was created…
When a customer paid through DPO, they landed on the DPO error page ("Not Valid - this transaction is no longer valid") instead of the payment page, even though the transaction token was created correctly.
The customer is redirected to `https://secure.3gdirectpay.com/payv2.php` with the transaction token passed as the `ID` parameter. `payv2.php` answers with a 302 redirect to `payv3.php`. Per HTTP semantics, a 302 turns the request into a GET and drops the body, so when `ID` is sent in the body of a POST it never reaches `payv3.php`: the customer arrives at `payv3.php?` with no token and DPO rejects it as invalid.
This regressed with 97ec8a3e72d9d48a0a9620c53feea533421b9d67, which moved redirect providers to the generic redirect form. Before that commit, the token was part of the action URL itself (`payv2.php?ID=<token>`), so it stayed in the query string across the redirect. The refactor moved `ID` into `url_params` rendered as a hidden input, and since `http_method` was left unset the generic form defaults to POST, putting `ID` in the body.
Set `http_method` to "get" so the token is serialized back into the query string and survives the `payv2.php` -> `payv3.php` redirect, restoring the pre-refactor behavior. This also matches DPO's documented convention of passing the token in the URL query string.
opw-6312732
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#272890The attendance timesheet report now explicitly identifies the database columns it uses, preventing errors when customer customizations add similarly named fields. This keeps the report reliable and avoids unexpected failures during report generation.
Original PR description
In `hr_timesheet_attendance_report`, the SQL query was using unqualified columns (e.g. `date` instead of `ts.date`)
It was not an issue in standard, but if a customer adds a `date` or `check_in` column to `hr_employee`, the query becomes ambiguous and fails.
To solve the issue, we explicitly qualify `ts.date` and `hr_attendance.check_in`.
upg-4445460
```python
File "/home/odoo/src/odoo/19.0/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py", line 24, in init
self.env.cr.execute("""CREATE OR REPLACE VIEW %s AS (
File "/home/odoo/src/odoo/19.0/odoo/sql_db.py", line 440, in execute
self._obj.execute(query, params)
psycopg2.errors.AmbiguousColumn: column reference "date" is ambiguous
LINE 44: AND date <= CURRENT_DATE
```
Forward-Port-Of: odoo/odoo#274482
Forward-Port-Of: odoo/odoo#274341This change fixes a stock handling issue where items could be lost from the process after being unreserved and reserved again during validation. As a result, package checks are now applied correctly for all relevant transfers, reducing the risk of incorrect stock validation results.
Original PR description
This reverts commit 5d70f75f1d27577ee4e2121497ce477cfa6cda53. `free_reservation` is called once per move line to validate. The goal is to unlink potential move lines that have the same reservation. After finding them, a force re-reservation is triggered. The idea of the previous commit was to call `check_entire_pack` (caused by the re-reservation) only once and not at each move line `free_reservation`. The issue is the stock move that has been unreserved then re-reserved are lost in the process and only the picking that had at least one move line validated are actually calling `check_entire_pack`. 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#273813 Forward-Port-Of: odoo/odoo#273658
The print button on customer invoices is being restored to its primary position. This removes a confusing change and keeps the button prominent unless the invoice has already been sent, where the secondary style still makes sense.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
This fix restores PDF generation for Polish e-invoices when QR codes are included. A previous change caused the document creation step to fail, and this update removes the extra data encoding that was breaking the process.
Original PR description
Due to this (https://github.com/odoo/odoo/pull/244421/changes/546a4425884e61080a7a7e8d2b2a97c8a2e3f38e), PDF generation was broken. Removing the manual encoding of the data. Runbot [link](https://runbot.odoo.com/odoo/error/941292) runbot-941292 Forward-Port-Of: odoo/odoo#274424
The website title form now uses a style that can be edited in the visual editor, instead of a fixed alignment setting. This makes it easier for users to change how the title is displayed directly from the website editor.
Original PR description
`s_title_form` comes with the `text-center` utility class which forbids edition through the web_editor, it needs to use inline-style instead. task-6149380 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263334
This update adjusts a system setting so it points to the demo environment instead of a test one. It helps ensure the account EDI proxy uses the intended setup for the current users and avoids misconfiguration.
Original PR description
The system parameter is already brought to demo in account_peppol module. But the current users are not for pdp. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272462
Credit notes for returned drop-shipped tracked products will now show the correct lot or serial number on the invoice. This fixes a reporting error that could otherwise confuse customers and accounting teams when reviewing returns.
Original PR description
**Issue** Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print -> The generated PDF displays "lot1" instead of "lot2"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 1` since the credit is on a quantity of 1 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80 which would make it as -1 (since `qties_per_lot[sml.lot_id]` is 0 for the first iteration of `sml.lot_id`). Thus, it does not pass by this code (since quantity is greater than 0): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L87-L90 which would make it as 0.
- for the last one, `is_stock_return = False` as it should be, thus the quantity is 1 as it should be. The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 0, lot2: 1}`
The report then selects the first matching lot and stops: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6230281
Forward-Port-Of: odoo/odoo#268905
Forward-Port-Of: odoo/odoo#266716Credit note XML imports now keep quantities and tax amounts positive when bringing in Belgian e-invoices. This prevents taxes from being subtracted by mistake and ensures totals are calculated correctly for accounting users.
Original PR description
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as…
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as a negative value which is corrected with a rounding line. - The 6% tax rate is applied to the negative invoice line, resulting in a negative tax amount being deducted from the total (e.g., 449.32 + (-26.96) = 422.36) instead of being added (449.32 + 26.96 = 476.28) Expected behavior: price_unit, quantity and the related tax amounts should all be positive, matching a normal in_refund/out_refund line. Why this happens: - In `_import_ubl_invoice_line_add_price_unit_quantity_discount`, `BaseQuantity` was multiplied by file_document_sign, unlike `PriceAmount` from the same node which is left untouched. This flips price_quantity to -1, which later flips price_unit to negative when `price_unit = price_subtotal / price_quantity`. opw-6310442 Forward-Port-Of: odoo/odoo#271148
This update fixes a crash that could happen when signing customer invoices using the Egyptian ETA USB certificate. Invoice signing now correctly reads the certificate data, so users can complete the signing process without interruption.
Original PR description
Steps to reproduce: - Configure a thumb drive with a certificate read from the ETA USB tool, so l10n_eg_edi.thumb.drive.certificate is populated - Open a customer invoice, confirm it, then Sign…
Steps to reproduce:
- Configure a thumb drive with a certificate read from the ETA USB tool, so l10n_eg_edi.thumb.drive.certificate is populated
- Open a customer invoice, confirm it, then Sign invoice
Before this commit, signing crashed with:
`TypeError: encoded_data must be a byte string, not
odoo.orm.fields_binary.BinaryValueAttachment`
raised by `asn1crypto` in `x509.Certificate.load()`, called from `_generate_signed_attrs__` and identically from `_generate_signer_info__` and `_generate_cades_bes_signature`.
Reading an attachment-backed Binary field now returns a lazy `BinaryValueAttachment` wrapper rather than raw bytes, and `asn1crypto` rejects any value that is not a bytes instance. `set_certificate` and the `l10n_eg_eta_json_doc_file` reads were already moved to the new binary API but the three certificate loads were missed and still passed the wrapper straight to asn1crypto.
Load the certificate through `self.certificate.content`, which returns the stored DER bytes.
opw-6365281
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274658This update corrects the way Belgian eco-cheques are computed in payroll. It helps ensure employee payslips reflect the right amount after the related date-handling logic was adjusted.
Original PR description
Forward-Port-Of: odoo/odoo#267657
The Registration Desk now updates immediately whenever the Registration Summary dialog is closed, including when users press Escape or click outside the dialog. This prevents stale attendee information from staying on screen and ensures the Kanban and List views always reflect the latest status.
Original PR description
**Current behavior before PR:** Closing the Registration Summary dialog by pressing **Escape** or clicking outside the dialog does not refresh the Registration Desk view. As a result, the attendee state is not reflected until the view is manually reloaded. **Desired behavior after PR is merged:** The Registration Desk view is refreshed whenever the Registration Summary dialog is closed, regardless of whether it is closed using the **Close** button, by pressing **Escape**, or by clicking outside the dialog. This ensures the attendee information is always updated in both the Kanban and List views. Task - [#6333829](https://www.odoo.com/odoo/project.task/6333829) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272699
11 changes
Enhancements to existing features
The Azerbaijani Manat (AZN) now uses its official currency symbol, ₼, in Odoo. This improves consistency and makes financial documents and displays more accurate for users working with this currency.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
Backorder creation during receipt validation has been optimized so it no longer slows down or times out on very large operations. This should make large warehouse processing more reliable and reduce the risk of database memory errors.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667 Forward-Port-Of: odoo/odoo#273555 Forward-Port-Of: odoo/odoo#269350
This change makes the tax supply date available for companies using the German localization. It helps ensure tax reporting can reflect the correct supply timing, which supports more accurate compliance handling.
Original PR description
Forward-Port-Of: odoo/odoo#272461
Resolved issues and error corrections
Fixed an error that could appear when a chatbot tries to hand a conversation to an operator but none are available in the live chat channel. Instead of showing an error, the chat now handles this case cleanly, improving reliability for website visitors and support teams.
Original PR description
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install…
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install ``im_livechat`` module with demo data - Go to Live Chat > Configuration > Chatbots > Create a new chatbot > Add script > Step Type: Question > Set answers > Save > Add script > Step Type: Forward to operator > Only If: Set one of the above answers > Save - Go to Live chat > Channel > Click the configure channel on YourWebsite.com > Remove the operators > Save - Go to the chatbot > test > select the configured answer Traceback: ```py StopIteration ``` https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/im_livechat/controllers/chatbot.py#L65-L70 When the chatbot script reaches a Forward to operator step while no operator is configured in the live chat channel, no chatbot message is created. As a result, the generator iterates over an empty iterator, and the ``next()`` call raises a ``StopIteration`` exception, causing a traceback during the conversation. sentry-7435424405 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274615 Forward-Port-Of: odoo/odoo#261726
Pakistan’s currency symbol (PKR) will now appear before the amount instead of after it. This aligns displays with local market practice and helps make invoices and prices look more familiar to users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
This update adjusts how an invoice import test checks partner bank account retrieval, using a smaller prebuilt XML sample instead of a generated file. It makes the test more reliable and easier to maintain without changing the business behavior of invoice imports.
Original PR description
Move the partner retrieval bank account number test to the `test_ubl_import_bis3_invoice_be_retrieve_partner.py` file and use a partial XML instead of a generated XML. Forward-Port-Of: odoo/odoo#274591 Forward-Port-Of: odoo/odoo#269995
Installing the Uruguay localization on demo databases no longer fails with a validation error. The change removes a redundant setting that was being applied twice, which avoids an error on journals that already contain validated entries.
Original PR description
**Issue:** Installing `l10n_uy` on a demo database raises a ValidationError from the `check_use_document` constraint since 19.3+. The error occurs because `ir_module.py:write()` re-applies…
**Issue:** Installing `l10n_uy` on a demo database raises a ValidationError from the `check_use_document` constraint since 19.3+. The error occurs because `ir_module.py:write()` re-applies module-specific template data to all companies with a matching chart template after installation. At that point, `demo_company_uy` already exists with `chart_template='uy'` and posted demo invoices, so `_load_data` ends up writing `l10n_latam_use_documents=True` to a journal that has validated entries. This write was previously suppressed by `_pre_reload_data`, which unconditionally removed journals from the data when found by xmlid. Commit 056b8e38ff84 (saas-19.3) narrowed that protection to only apply when `'type' in journal_data`. Since the module-filtered data never includes `type` (that field comes from `_get_account_journal` in the base `account` module, excluded by the module filter), the journal is no longer protected and the write triggers the constraint. **Versions:** 19.3+ **Fix:** remove `l10n_latam_use_documents=True` from `_get_uy_account_journal`. `l10n_latam_invoice_document` already sets this field for all LATAM companies via `_get_latam_document_account_journal`; l10n_uy was setting it redundantly. Task id: [6354499](https://www.odoo.com/odoo/project/49/tasks/6354499)
Invoices sent through Nilvera could get stuck with an intermediate status and stop being checked too early. This change keeps those invoices in the follow-up process until Nilvera provides the final result, reducing cases where documents appear permanently unresolved.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311This update prevents the attendance timesheet report from breaking when custom fields with common names are added to employee records. It makes the database query more precise so the report continues to load correctly in customized databases.
Original PR description
In `hr_timesheet_attendance_report`, the SQL query was using unqualified columns (e.g. `date` instead of `ts.date`)
It was not an issue in standard, but if a customer adds a `date` or `check_in` column to `hr_employee`, the query becomes ambiguous and fails.
To solve the issue, we explicitly qualify `ts.date` and `hr_attendance.check_in`.
upg-4445460
```python
File "/home/odoo/src/odoo/19.0/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py", line 24, in init
self.env.cr.execute("""CREATE OR REPLACE VIEW %s AS (
File "/home/odoo/src/odoo/19.0/odoo/sql_db.py", line 440, in execute
self._obj.execute(query, params)
psycopg2.errors.AmbiguousColumn: column reference "date" is ambiguous
LINE 44: AND date <= CURRENT_DATE
```
Forward-Port-Of: odoo/odoo#274482
Forward-Port-Of: odoo/odoo#274341This change restores the earlier behavior for warehouse validation so all affected stock moves are correctly re-checked after reservations are released and reassigned. It prevents some items from being skipped in the process, which helps keep packing and reservation status accurate.
Original PR description
This reverts commit 5d70f75f1d27577ee4e2121497ce477cfa6cda53. `free_reservation` is called once per move line to validate. The goal is to unlink potential move lines that have the same reservation. After finding them, a force re-reservation is triggered. The idea of the previous commit was to call `check_entire_pack` (caused by the re-reservation) only once and not at each move line `free_reservation`. The issue is the stock move that has been unreserved then re-reserved are lost in the process and only the picking that had at least one move line validated are actually calling `check_entire_pack`. 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#273813 Forward-Port-Of: odoo/odoo#273658
The Print button on customer invoices is being restored to its previous primary position. This corrects a confusing change so the most important action is again presented clearly, while keeping the secondary style only for cases where the document has already been sent.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
9 changes
Enhancements to existing features
When users resize tables, the horizontal scrollbar now appears on the table itself instead of affecting the whole editor area. Existing resized tables are also updated automatically when the editor loads, so the behavior is consistent for old and new content.
Original PR description
#### Description of the issue this PR addresses: - Resized tables stored their width on the `table` element. When such tables became wider than the editable area, a horizontal scrollbar appeared on the main editable. #### Desired behavior after PR is merged: - Width handling is now moved to `tbody` so the scrollbar stays on the table itself instead of the editable. - This PR also updates already resized tables when loading the editor to ensure they follow the same behavior. task-5123011 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272977
The Azerbaijani Manat (AZN) now uses its official symbol, ₼, in Odoo. This improves accuracy and consistency when displaying prices and financial reports for users working with this currency.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
This update speeds up the creation of backorders when validating receipts with many operations. It also prevents database memory issues by reducing the size of the conditions sent to PostgreSQL, making large stock operations complete more reliably and much faster.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667 Forward-Port-Of: odoo/odoo#273555 Forward-Port-Of: odoo/odoo#269350
Resolved issues and error corrections
The Project smart button on a confirmed sales order now opens the linked project as expected, even when the order has no sales order lines. This fixes a case where the button was visible but did not respond, improving access to the related project information.
Original PR description
Steps to reproduce: - - Create a sale order. - Link a project using the Project field. - Confirm the sale order. - Click on the Project smart button. Issue: - The Project smart button is displayed since the sale order has a linked project. However, clicking on it does nothing. Cause: - A sale order without order lines can still have projects linked through the project_id field. The action should not assume that no order lines means there are no projects to display. Solution: - Remove the unnecessary order line check and allow the existing logic to open the linked projects. task-6209658 Forward-Port-Of: odoo/odoo#270752
This fix prevents a crash in live chat when a chatbot tries to hand a visitor over to an operator but none are configured. Instead of showing an error, the conversation now ends gracefully, improving reliability for visitors and support teams.
Original PR description
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install…
When a live chat channel has no operators configured and the chatbot script ends with a Forward to operator step, triggering that step causes a traceback. Steps to reproduce the error: - Install ``im_livechat`` module with demo data - Go to Live Chat > Configuration > Chatbots > Create a new chatbot > Add script > Step Type: Question > Set answers > Save > Add script > Step Type: Forward to operator > Only If: Set one of the above answers > Save - Go to Live chat > Channel > Click the configure channel on YourWebsite.com > Remove the operators > Save - Go to the chatbot > test > select the configured answer Traceback: ```py StopIteration ``` https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/im_livechat/controllers/chatbot.py#L65-L70 When the chatbot script reaches a Forward to operator step while no operator is configured in the live chat channel, no chatbot message is created. As a result, the generator iterates over an empty iterator, and the ``next()`` call raises a ``StopIteration`` exception, causing a traceback during the conversation. sentry-7435424405 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274615 Forward-Port-Of: odoo/odoo#261726
Pakistan’s currency symbol now appears before the amount instead of after it. This brings the display in line with local market practice and makes currency formatting more familiar for users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
The Point of Sale receipt now shows the rounded amount actually paid in the “To Pay” section, instead of the unrounded total due. This makes cash-rounded receipts clearer and matches the behavior users expected before, avoiding confusion when the receipt shows a higher amount than what was paid.
Original PR description
**Steps to reproduce:** - Create a rounding method, only for cash, rounding of 100 - Create a product, costing 100 - Go to the PoS, order and pay for the product with cash - The "To Pay" section is the total due, and not what we actually paid - It is 115 but it should be 100 as this is what we pay for **Why the fix:** The current behavior is to display the total due, not rounded, just everything we have to pay for. Before 19.0, what we paid for was displayed, in this exemple it would display 100 and not 115. This is correct as it seems it is what this section of the receipt is about. We now use **total_amount_currency** which is computed like this https://github.com/odoo/odoo/blob/006a6a1cc6e50bd8b328d0cabb7abbcf610e34bb/addons/account/static/src/helpers/account_tax.js#L1411-L1414 So it is the price + the tax + the rounding, in this exemple it would be **100 + 15 + (-15)** opw-6225613 Forward-Port-Of: odoo/odoo#274176 Forward-Port-Of: odoo/odoo#265298
This fix ensures invoices sent through Nilvera are checked again even when they temporarily show as “Unknown.” That prevents documents from getting stuck in an unfinished state and helps the final status appear correctly once Nilvera completes its processing.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311This change prevents the timesheet attendance report from failing when custom fields with common names are added to employee records. It makes the database query more specific, so the report keeps working reliably in customized systems.
Original PR description
In `hr_timesheet_attendance_report`, the SQL query was using unqualified columns (e.g. `date` instead of `ts.date`)
It was not an issue in standard, but if a customer adds a `date` or `check_in` column to `hr_employee`, the query becomes ambiguous and fails.
To solve the issue, we explicitly qualify `ts.date` and `hr_attendance.check_in`.
upg-4445460
```python
File "/home/odoo/src/odoo/19.0/addons/hr_timesheet_attendance/report/hr_timesheet_attendance_report.py", line 24, in init
self.env.cr.execute("""CREATE OR REPLACE VIEW %s AS (
File "/home/odoo/src/odoo/19.0/odoo/sql_db.py", line 440, in execute
self._obj.execute(query, params)
psycopg2.errors.AmbiguousColumn: column reference "date" is ambiguous
LINE 44: AND date <= CURRENT_DATE
```
Forward-Port-Of: odoo/odoo#274482
Forward-Port-Of: odoo/odoo#27434121 changes
Enhancements to existing features
The Azerbaijani Manat (AZN) now uses its official symbol, ₼, in the system. This improves display accuracy for users working with Azerbaijani currency and helps ensure printed and on-screen documents look correct.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
When users resize tables in the editor, the horizontal scrollbar now appears on the table itself instead of expanding the whole editing area. Existing resized tables are also updated automatically, so the behavior is consistent when reopening content. This makes table editing smoother and avoids layout issues in the editor.
Original PR description
#### Description of the issue this PR addresses: - Resized tables stored their width on the `table` element. When such tables became wider than the editable area, a horizontal scrollbar appeared on the main editable. #### Desired behavior after PR is merged: - Width handling is now moved to `tbody` so the scrollbar stays on the table itself instead of the editable. - This PR also updates already resized tables when loading the editor to ensure they follow the same behavior. task-5123011 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272977
Creating backorders for large receipts is now much faster and less likely to fail when many stock operations are involved. This improves validation times for high-volume warehouse transactions and helps prevent system timeouts and database memory errors.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667 Forward-Port-Of: odoo/odoo#273555 Forward-Port-Of: odoo/odoo#269350
This update makes the tax supply date available for German accounting flows. It helps businesses record the correct date for tax reporting, reducing manual work and the risk of inconsistencies in local compliance processes.
Original PR description
Forward-Port-Of: odoo/odoo#272461
Resolved issues and error corrections
Pakistan’s currency symbol (PKR) is now shown before the amount instead of after it. This makes currency formatting match common market practice and improves the clarity of displayed amounts for users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
This change corrects overtime totals for employees on flexible weekly schedules when public holidays are involved. It ensures leave time is calculated properly across time zones, so extra hours are shown accurately instead of being overstated.
Original PR description
Currently, flexible weekly overtime deducts the raw leave interval duration. ## **Steps to reproduce:** - Install hr_holidays and hr_attendance - Create an employee with flex 40h/week working…
Currently, flexible weekly overtime deducts the raw leave interval duration. ## **Steps to reproduce:** - Install hr_holidays and hr_attendance - Create an employee with flex 40h/week working schedule. - Employee profile>setting>Default Ruleset>Employee schedule Rule and set `If the worked hours on a`: `week`. - Create a public holiday on Monday. - Record daily 8h from Tue to Sat (12 AM to 8 AM). ## **Observed Behavior:** Attendance List View computes "Worked Extra Hours" incorrectly as 20:30h ## **Expected Behavior:** "Worked Extra Hours" should be computed as 8h ## **Root Cause:** In [_get_daterange_overtime_undertime_intervals_for_quantity_rule](https://github.com/odoo/odoo/blob/53448e5445c8bcbf12126bf27bd675f4b9883d05/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L290-L342), the system manually calculates overtime for flexible employees by deducting `schedule['leave']` durations from the expected working hours at [1]. However, for global public holidays, the system mishandles the timezone conversion within this schedule dictionary. Because public holiday intervals are stored and processed using UTC datetimes before being converted to the employee's local timezone, converting it to the employee's local timezone causes the holiday hours to shift and overlap into the next calendar day. As a result, the `schedule['leave']` calculation incorrectly thinks the employee had time off on normal working days, which throws off the final overtime amount. [1]: http://github.com/odoo/odoo/blob/53448e5445c8bcbf12126bf27bd675f4b9883d05/addons/hr_attendance/models/hr_attendance_overtime_rule.py#L304-L307 ## **Fix:** Replace the manual leave subtraction logic with the existing `_get_expected_hours_from_contract` method. This method naturally handles global public holidays and computes attendance intervals safely across different timezones without shifting hours into the wrong day. **opw-6259328,6284145** Forward-Port-Of: odoo/odoo#269293
The Project smart button on sales orders now works even when the order has no order lines. This fixes a situation where a linked project was visible but clicking it did nothing, making it easier for users to access the related project directly.
Original PR description
Steps to reproduce: - - Create a sale order. - Link a project using the Project field. - Confirm the sale order. - Click on the Project smart button. Issue: - The Project smart button is displayed since the sale order has a linked project. However, clicking on it does nothing. Cause: - A sale order without order lines can still have projects linked through the project_id field. The action should not assume that no order lines means there are no projects to display. Solution: - Remove the unnecessary order line check and allow the existing logic to open the linked projects. task-6209658 Forward-Port-Of: odoo/odoo#270752
Invoices sent through Nilvera could get stuck in an intermediate “Unknown” state and stop being checked again, even though Nilvera later updates them to a final result. This change makes Odoo keep polling those invoices until the final status is received, reducing manual follow-up and preventing invoices from remaining unresolved.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311The mailing editor’s snippet picker now appears in the correct place again when an AI chat is open. This prevents the editor from getting stuck and lets users continue saving, discarding, and adding content normally.
Original PR description
When an AI chatbox is active, all non-error dialog overlays are set to be behind the chatbox through their z-index. This causes an issue where the dialog overlay that adds new snippets to a mailing is placed behind the fullscreen mailing editor, preventing its use and freezing the use of some commands (save & discard). This commit restores the snippet dialog's z-index to its original value. Steps to reproduce: - Create a new mailing - Select a builder-enabled theme (such as Events Promo) - Open a new AI chat by clicking the AI icon in the top right - Open the fullscreen editor - Click on the Headers block category task-6321624 Forward-Port-Of: odoo/odoo#274715
This change restores the previous reservation check so packs are handled correctly when inventory reservations are freed and reassigned during validation. It prevents some stock moves from being lost in the process, which helps ensure the correct picking is updated and stock operations stay accurate.
Original PR description
This reverts commit 5d70f75f1d27577ee4e2121497ce477cfa6cda53. `free_reservation` is called once per move line to validate. The goal is to unlink potential move lines that have the same reservation. After finding them, a force re-reservation is triggered. The idea of the previous commit was to call `check_entire_pack` (caused by the re-reservation) only once and not at each move line `free_reservation`. The issue is the stock move that has been unreserved then re-reserved are lost in the process and only the picking that had at least one move line validated are actually calling `check_entire_pack`. 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#273813 Forward-Port-Of: odoo/odoo#273658
This change fixes an unreliable automated test in the messaging app. The test now matches how the product really works, so it should stop failing randomly and give more dependable results for future updates.
Original PR description
The `bus subscription is refreshed when channel is joined` test is sometimes failing. This test doesn't make sense: it opens the command palette and wait for a subscription to be made. However, a subscription is only done when needed (opening the thread or being a member of the channel). The step was satisfied by luck. This commit fixes the test to reflect production code: the subscription is made once the channel is opened. runbot-941462 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#274741
The print button on customer invoices is changed back to its original primary style. This reduces confusion and keeps the button appearance consistent unless the invoice has already been sent, where the secondary style still applies.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
This fix ensures products tracked by lots get the right cost when their inventory comes from purchases with different prices. As a result, both the lot cost and the product's standard price are calculated accurately, which improves stock valuation and financial reporting.
Original PR description
This PR is needed for the fix of https://github.com/odoo/odoo/pull/272411 **Problem:** lot's standard price are not correct when the product is fifo and move have different values and multiple lots…
This PR is needed for the fix of https://github.com/odoo/odoo/pull/272411 **Problem:** lot's standard price are not correct when the product is fifo and move have different values and multiple lots **Steps to reproduce:** - product fifo tracked and valued by lots - 20 IN @ 100 (all in lot 1) - 10 IN @ 10 (5 in lot 1 and 5 in lot 2) - on the product form click on the lot/serial number smart button and select lot 1 **Current behavior:** the average cost of lot1 is 64 back on the product form the standard price is 55 **Expected behavior:** the average cost of lot 1 should be 20 * 100 (from move1) + 5 * 10 (from move 2) / 25 = 2050 / 25 = 82 the standard price of the product should be 2100 / 30 = 70 **Cause of the issue:** Because the product is fifo, to compute the avg_cost of the lot we call _run_fifo() https://github.com/odoo/odoo/blob/456026b5ef99388b1cf5bdd78cee8d1ad3d51304/addons/stock_account/models/stock_lot.py#L47 which calls _run_fifo_get_stack() to get the fifo stack specific to this lot. https://github.com/odoo/odoo/blob/456026b5ef99388b1cf5bdd78cee8d1ad3d51304/addons/stock_account/models/product.py#L545 Issue 1) run_fifo_get_stack() stores the on hand quantity (for the lot if a lot is given as param) in fifo_stack_size and, as long as there is moves and fifo_stack_size>0, adds move (starting from the last one in date) to the stack and removes the quantity of the move from fifo_stack_size. It then returns the moves stack and the remaning quantity on the first move of the stack (for the rest we know it's the full quantity) https://github.com/odoo/odoo/blob/456026b5ef99388b1cf5bdd78cee8d1ad3d51304/addons/stock_account/models/product.py#L612-L618 Inside run_fifo_get_stack(), to do this, because we're only considering the quantities from this specific lot we should only remove the quantity from the move that went in lot, but currently we're removing the quantity from the entire move. https://github.com/odoo/odoo/blob/456026b5ef99388b1cf5bdd78cee8d1ad3d51304/addons/stock_account/models/product.py#L615-L618 So, at the first iteration of the while loop (for the move with 10 quantities), instead of doing fifo_stack_size(25) -= 5, we do fifo_stack_size(25) -= 10 The next move is the last one, so it's the one on which remaining_qty_on_first_stack_move will be based on. remaining_qty_on_first_stack_move will be the minimum between the move's quantity and the fifo_stack_size. So because the fifo_stack_size is now wrongfully 15 instead of 20 that's the value that will be returned by _run_fifo_get_stack. So inside run_fifo(), qty_on_first_move will be 15 instead of 20 https://github.com/odoo/odoo/blob/456026b5ef99388b1cf5bdd78cee8d1ad3d51304/addons/stock_account/models/product.py#L545 Issue 2) Another issue is that inside _run_fifo when calling _get_valued on the move, we don't use the lot parameter. So we use the entire quantity of the move instead of the quantity specific to the lot. https://github.com/odoo/odoo/blob/b07ff5843ee87741b293d9e67f72a77a2ed2ed88/addons/stock_account/models/product.py#L561-L562 And we use the full value of the move instead of the pro rata of the value for the quantity specific to the lot As a consequence, inside _run_fifo the computation for the fifo_cost will be 15 (because of issue1) * 100 $ [first iteration of the while loop] \+ 10 (because of issue 2) * 10$ [second iteration of the while loop] = 1600$ Instead of 20 *100 + 5 *10$ = 2050$ Therefore the avg_cost of the lot is wrong and the standard price of the product will also be false. side note: those two issues balance each other if the price unit of the moves are the same needed for PR of opw-6311341 Forward-Port-Of: odoo/odoo#273728
This update changes the website title snippet so its text alignment can be adjusted directly in the editor. It removes a styling limitation that previously blocked users from changing alignment, making layout edits easier and more flexible.
Original PR description
`s_title_form` comes with the `text-center` utility class which forbids edition through the web_editor, it needs to use inline-style instead. task-6149380 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263334
This change updates a system setting so the payment proxy uses demo values instead of test values. It helps keep the environment consistent with the intended setup and avoids mismatched configuration for current users.
Original PR description
The system parameter is already brought to demo in account_peppol module. But the current users are not for pdp. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272462
This update adds a backup check for Mollie payments so confirmation can still be detected even if the real-time server connection is slow or unavailable. As a result, customers should no longer need to use the Force Done button in most cases and may only wait a few seconds for the payment to complete.
Original PR description
Due to the unreliability of the bus during peak server times, clients were missing the websocket payment confirmations from the backend. This meant they had to use the Force Done button to confirm the payment. This commit adds a polling mechanism similar to that used for Viva.com, which polls the backend directly every 5 seconds to check the status of the payment. This means that instead of being blocked, the client should only experience at most a 5 second delay, even when the websocket isn't working. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274713
When a Point of Sale order line quantity was changed during a refund, the system was not applying the order’s fiscal position when recalculating taxes and prices. This fix ensures the correct tax mapping is used, so refunded amounts stay consistent and accurate.
Original PR description
When changing the quantity of a pos order line the fiscal position set on the order was not used when recomputing the line price and taxes. Steps to reproduce: ------------------- * Create a tax with 15% rate and another with 10% rate * Create a fiscal position that maps the 15% tax to the 10% tax * Setup a PoS to be able to use that fiscal position * Open the PoS, add a product with the 15% tax, set the fiscal position and validate the order * Refund the order in the backend and change the quantity of the line from -1 to 0 and back to -1. > Observation: The price is not the same as before Why the fix: ------------ The fiscal position was not applied when recomputing the line's price and taxes. opw-6253311 Forward-Port-Of: odoo/odoo#274463 Forward-Port-Of: odoo/odoo#270135
Credit notes imported from UBL/XML now keep the line price and tax amounts positive when they should be, instead of being incorrectly flipped negative. This fixes incorrect totals on Belgian credit note imports and prevents undercharging or over-deducting tax amounts.
Original PR description
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as…
Steps to reproduce: 1. Install l10n_be and switch to BE company 2. Upload the XML document (found in ticket chatter) into the Accounting application as a Credit Note. Issue: - The line is imported as a negative value which is corrected with a rounding line. - The 6% tax rate is applied to the negative invoice line, resulting in a negative tax amount being deducted from the total (e.g., 449.32 + (-26.96) = 422.36) instead of being added (449.32 + 26.96 = 476.28) Expected behavior: price_unit, quantity and the related tax amounts should all be positive, matching a normal in_refund/out_refund line. Why this happens: - In `_import_ubl_invoice_line_add_price_unit_quantity_discount`, `BaseQuantity` was multiplied by file_document_sign, unlike `PriceAmount` from the same node which is left untouched. This flips price_quantity to -1, which later flips price_unit to negative when `price_unit = price_subtotal / price_quantity`. opw-6310442 Forward-Port-Of: odoo/odoo#271148
The Registration Desk now refreshes automatically whenever the Registration Summary dialog is closed, no matter how it is dismissed. This keeps attendee status and changes visible immediately, reducing confusion and avoiding manual page reloads.
Original PR description
**Current behavior before PR:** Closing the Registration Summary dialog by pressing **Escape** or clicking outside the dialog does not refresh the Registration Desk view. As a result, the attendee state is not reflected until the view is manually reloaded. **Desired behavior after PR is merged:** The Registration Desk view is refreshed whenever the Registration Summary dialog is closed, regardless of whether it is closed using the **Close** button, by pressing **Escape**, or by clicking outside the dialog. This ensures the attendee information is always updated in both the Kanban and List views. Task - [#6333829](https://www.odoo.com/odoo/project.task/6333829) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272699
This fix stops counted inventory quantities from being cleared to zero when users move between lines without typing a new value. It ensures the quantity is only updated after a manual entry, reducing accidental data loss during physical inventory counts.
Original PR description
Versions -------- - 19.0+ Steps ----- 1. Open Physical Inventory; 2. click on a line; 3. click on a different line. Issue ----- Counted quantity automatically gets set to 0. Cause ----- Commit 3187030 changed the counted quantity widget to enable mutli-line edit. Part of this was done by ignoring the `onInput` hook, and always updating the counted quantity `onBlur`, making it so that the value is set to zero when clicking away, regardless of manual input. Solution -------- Use a `hasInput` state which gets set to `true` on user input. If not `true`, don't update the counted quantity on blur. opw-6365084 Forward-Port-Of: odoo/odoo#274364
This update fixes a flaky automated test in the Discuss full flow by making the scheduled activity dates consistent in every time zone. It matters because it prevents random test failures and helps keep the messaging activity counter working reliably during validation.
Original PR description
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so…
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so activity_schedule fell back to context_today on the class environment, whose superuser has tz Europe/Brussels with demo data. When the test runs between 22:00 and 00:00 UTC, that deadline is tomorrow from a UTC point of view. The state of an activity is however computed in the timezone of its assigned user, and hr_user is created without one, falling back to the server date (UTC). Its activities were therefore planned instead of today, the counter stayed empty and the tour timed out. The admin iteration kept passing because demo data gives admin the same Brussels timezone as the environment that computed the deadline, which is why only half the runs failed (both occurrences at 23:56 and 23:31 UTC). Schedule the activities with a deadline one week in the past instead: an old deadline is overdue in every timezone, whatever timezone the scheduling environment or the assigned user has, making the counter deterministic at any time of the day. https://runbot.odoo.com/odoo/error/941407 Forward-Port-Of: odoo/odoo#274679
7 changes
Enhancements to existing features
The Azerbaijani Manat (AZN) currency symbol has been updated to its official Unicode sign, ₼. This keeps currency displays accurate and consistent for users working with Azerbaijani accounts or pricing.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 Backport of: https://github.com/odoo/odoo/pull/262471 task-6112867 Forward-Port-Of: odoo/odoo#274368
Resolved issues and error corrections
Invoices sent through Nilvera could get stuck in an intermediate “Unknown” state and stop being checked again. This change makes Odoo keep polling those invoices until Nilvera returns the final result, preventing documents from remaining unresolved for too long.
Original PR description
## Short fix summary:
Nilvera reports `Unknown` as a normal, transient `StatusCode` value (their own e-Archive API docs
list the enum as `unknown`/`waiting`/`succeed`/`error`) right after a document is sent, before their
daily batch resolves the final status. But `_cron_nilvera_get_invoice_status`'s search domain only
matches `l10n_tr_nilvera_send_status in ('waiting', 'sent')`, so once an invoice lands on `unknown` it
is never polled again — even after Nilvera later resolves the real status on their side. This adds
`unknown` to that domain so these invoices keep getting polled until Nilvera reports a final status.
task-6328589
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#274494
Forward-Port-Of: odoo/odoo#274311This change restores the previous reservation check so stock packages are evaluated correctly while validating products. It prevents some stock moves from being skipped during re-reservation, which helps keep inventory records accurate and avoids missing follow-up processing.
Original PR description
This reverts commit 5d70f75f1d27577ee4e2121497ce477cfa6cda53. `free_reservation` is called once per move line to validate. The goal is to unlink potential move lines that have the same reservation. After finding them, a force re-reservation is triggered. The idea of the previous commit was to call `check_entire_pack` (caused by the re-reservation) only once and not at each move line `free_reservation`. The issue is the stock move that has been unreserved then re-reserved are lost in the process and only the picking that had at least one move line validated are actually calling `check_entire_pack`. 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#273658
The Print button on customer invoices is being changed back to the main action instead of a secondary one. This makes the invoice screen clearer and helps users quickly find the expected printing option, except in cases where the document has already been sent.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
This update corrects a display issue where numbers with many decimal places could sometimes show an extra incorrect digit, such as 53000.0000000002. It improves the accuracy of values shown in the interface, which helps users trust quantities and amounts displayed on screen.
Original PR description
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a…
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a trailing parasitic digit (such as 53000.0000000002 instead of 53000.0000000000). This commit resolves the issue by backporting the formatting logic from master. The `maxDecDigits` calculation is moved outside the conditionals so it unconditionally caps precision for all numbers. Furthermore, the global significant digit ceiling is reduced from 15 to 14. This 14-digit ceiling reserves a 1-digit buffer, allowing the newly introduced `formatFixedDecimals` utility to safely run `roundDecimals` on the float. This mathematically sanitizes the trailing corrupted digit before it is ever converted to a string. opw-6313540 **Current behavior before PR:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed with a corrupted digit (e.g. 53000.0000000002) **Desired behavior after PR is merged:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed without corrupted digits (e.g. 53000.000000000) This PR is essentially a backport of https://github.com/odoo/odoo/commit/07da917f6e3319b4acde1029e77f69f1aba314b8 and https://github.com/odoo/odoo/commit/c4e7ba8d8fdfd7b0c442cf834f562ef8cedf019b for numbers.js Forward-Port-Of: odoo/odoo#272940
This change updates a system setting so the EDI proxy client is neutralized to a demo state instead of a test state. It helps ensure the configuration matches the intended use for current users and avoids confusion in the setup.
Original PR description
The system parameter is already brought to demo in account_peppol module. But the current users are not for pdp. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272462
This fix ensures that when an event’s dates are changed, attendee records are updated with the new start date before an email is sent. As a result, the email content now reflects the current event schedule instead of showing outdated information.
Original PR description
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to…
Steps to reproduce: ------------------------------------------------ 1. Install Event module 2. Create a multi day event 3. Create one attendee for the event 4. Change the event dates 5. Go to attendee and Click on Send by Email Observation: ------------------------------------------------ The event start date displayed in the email body is not updated after the event dates are modified. Issue: ------------------------------------------------ In `saas-18.2`, `event_begin_date` and `event_end_date` were simple related fields that automatically updated when their source fields changed. https://github.com/odoo/odoo/blob/saas-18.2/addons/event/models/event_registration.py#L57-L58 However, in `saas-18.3`, slots were introduced and these fields were converted to computed fields https://github.com/odoo/odoo/pull/205945/changes/e2bf8a89d6a50bd40f4673bef38176465f83ba0f * `event_begin_date` is made stored for cohort view grouping * However, the base compute method only depends on `event_id` and `event_slot_id` https://github.com/odoo/odoo/blob/ac37b479321dbe9dbf864e833900e043b1cc70df/addons/event/models/event_registration.py#L177-L180 * When you change `event.date_begin` or `event.date_end`, the registration records don't recompute because the dependency is on the `event_id`, not on the related date fields (`event_id.date_begin`, `event_id.date_end`) * Non-stored computed fields recalculate on-the-fly when accessed, so `event_end_date` appeared to work * Stored computed fields only recalculate when their explicit dependencies change Solution: ------------------------------------------------ * Corrected the dependencies of `_compute_event_begin_date`. * Added tests in the enterise module as issue occurs on installing enterprise module only. opw-6284576
20 changes
New functionality added to Odoo
Singapore companies can now use SFRS-compliant balance sheet and profit and loss reports directly in Odoo. This helps local businesses prepare financial statements aligned with Singapore reporting requirements with less manual setup.
Original PR description
Add the SFRS-compliant balance sheet and profit and loss reports for the Singapore localization. task-6159102
Enhancements to existing features
The Philippine payroll module now defines which payroll data should be kept up to date automatically. This helps ensure standard salary rules stay current through the scheduled payroll update process, reducing manual maintenance for customers.
Original PR description
Currently, the "Payroll: Update data" cron doesn't work for HK payroll as we never set up the _get_data_files_to_update. We can set up the list of data files to keep up to date to better support our users by automatically keeping non-edited salary rules up to date. task-6360470 Forward-Port-Of: odoo/enterprise#122781
Resolved issues and error corrections
Creating a worksheet template from Field Service and opening it in Studio now correctly links the new template back to the related task or project. This prevents users from losing the selected worksheet setup after closing Studio and returning to their work.
Original PR description
Steps to reproduce: - Open Field Service - Go to any task and create a work sheet on the fly - In the wizard click on Design Template - Close the studio and go back to task Issue: - You can see that…
Steps to reproduce: - Open Field Service - Go to any task and create a work sheet on the fly - In the wizard click on Design Template - Close the studio and go back to task Issue: - You can see that the newly created worksheet is not set Cause: - The reason for not getting set is due to fact that worksheet template is created after we click on Design Template which is a widget of view_widgets. - Therefore the field doesn't get dirty and doesn't get saved. Solution: - By sending a ORM write method that links the worksheet based on res_id and res_model. Technical: - The primary cause the problem occurs is that the worksheet template id is not getting created so worksheet_template_id in the respective model(i.e., project.task or project.project for now) is not getting dirty and the record (project.task or project.project) is not getting saved. - The worksheet template when clicked on "Design Template" button is created with in the widget which redirects to Studio for designing template. - We give the user/dev a chance to pass changed/tampered field name with in the context. - While trying to link worksheet template we check if we received field name from context or else go with default name "worksheet_template_id". - If the write(linnking fails) when throw a error notification as "The worksheet template field name seems to be tampered with, pass it in the context as <b>default_worksheet_template_field_name</b>" Also the only fly creation of worksheet is available only in industry_fsm_report but when it added in other modules such as maintenance this cause the same problem in all the other modules as well when we add Design Template Button. task-3871593
Creating a worksheet template from a service task now properly attaches it to the task after returning from the design screen. This prevents users from losing their newly created worksheet selection and helps the same flow work reliably in other worksheet-enabled areas such as maintenance.
Original PR description
Steps to reproduce: - Open Field Service - Go to any task and create a work sheet on the fly - In the wizard click on Design Template - Close the studio and go back to task Issue: - You can see that the newly created worksheet is not set Cause: - The reason for not getting set is due to fact that worksheet template is created after we click on Design Template which is a widget of view_widgets. - Therefore the field doesn't get dirty and doesn't get saved. Solution: - By sending a ORM write method that links the worksheet based on res_id and res_model. Also the only fly creation of worksheet is available only in industry_fsm_report but when it added in other modules such as maintenance this cause the same problem in all the other modules as well. task-3871593
The document selection window no longer shows document management actions that are not relevant when choosing files to attach or link. This reduces confusion and helps users focus on selecting the right documents.
Original PR description
When selecting documents for attachment/link, control panel actions were displayed upon selection. The document selection dialog uses the secondary documents view introduced in: https://github.com/odoo/enterprise/pull/89030/changes/f93c159c106d1dde70910ec590f8739e549b19cf Several document management actions were already hidden through the `documents_view_secondary` context, but `DocumentsAction` was still displayed upon selection. Hide `DocumentsAction` in the secondary view. Task-6236888 Forward-Port-Of: odoo/enterprise#122536 Forward-Port-Of: odoo/enterprise#119219
This fix ensures the recruitment reports feature includes the required component for cohort reporting. It prevents installation failures in specific setup scenarios, helping deployments complete smoothly.
Original PR description
installing hr_recruitment_reports with the --ski-auto-install flag causes an error. The error happens because it does not explicitly depend on web_cohort while displaying a cohort view. task-6352888 runbot_error-237854 Forward-Port-Of: odoo/enterprise#122432
The chatter now correctly shows the AI icon while an AI response is being prepared. This fixes a small visual issue so users can clearly recognize when the activity comes from the AI assistant.
Original PR description
This PR fixes an issue where the AI icon would not be shown on the thinking note of the chatter. The OWL3 migration added 'this.' prefixes to all template component references. This left 'isAiAgentChat' and 'props.channel' as bare context lookups (`ctx['isAiAgentChat']`, `ctx['props']`), both of which are undefined in the new rendering context. The fix adds 'this' in the xml to go through ctx['this'] to fetch each values correctly. task: 6346446 Forward-Port-Of: odoo/enterprise#122741
This update fixes an access problem affecting employee type handling in payroll tests. It helps keep payroll-related validation reliable and reduces the risk of incorrect test failures during development.
Original PR description
task-6348716 Forward-Port-Of: odoo/enterprise#122693 Forward-Port-Of: odoo/enterprise#122264
The invoice outstanding payments widget now displays payments in a consistent newest-first order using payment date and ID. This reduces confusion when users review available payments on invoices.
Original PR description
Before this commit: The invoice outstanding payments widget was not sorted by date globally, which could lead to confusion for users when viewing the widget. After this commit: This commit adds a sorting mechanism to ensure that the payments are displayed in descending order based on their date and ID. opw-6254080 Forward-Port-Of: odoo/enterprise#122964 Forward-Port-Of: odoo/enterprise#121642
Fixed an error that occurred when users clicked the AI button while preparing a signature request. This ensures the signature sending workflow remains usable and avoids disruption for users relying on AI assistance in the wizard.
Original PR description
Version: saas-19.3 Steps to Reproduce: 1. Open a sign template and click "Send" 2. Click the AI button in the wizard Issue: Clicking the AI button raises ValueError: "The record must inherit from 'mail.thread'". Cause: `sign.template` does not inherit `mail.thread`, but interfaceKey `mail_composer` requires it. Fix: Added `get interfaceKey()` to `MailComposerChatGPT` so subclasses can override it. `SignAIButton` in `sign_ai` overrides interfaceKey to `html_field_record`. Taskid: 6303226 Forward-Port-Of: odoo/enterprise#120659
Users can now audit Balance Sheet values when the report is grouped by analytic account without encountering an error. This keeps financial report drill-downs reliable and prevents interruptions during accounting analysis.
Original PR description
Currently an error occurs when user tries to audit a cell when Balance Sheet is grouped by an analytic acccount. Steps to replicate: - Install accountant with demo data and turn on Analytic…
Currently an error occurs when user tries to audit a cell when Balance Sheet is grouped by an analytic acccount.
Steps to replicate:
- Install accountant with demo data and turn on Analytic Accounting.
- Open Balance Sheet Report > Group By an Analytic Account > Click on Any Value under an Analytic Account Column.
Error:
```
File '/home/odoo/src/enterprise/saas-19.3/account_reports/models/account_report.py', line 2876, in dispatch_report_action
return report_method(model, *args)
File '/home/odoo/src/enterprise/saas-19.3/account_reports/models/balance_sheet.py', line 28, in action_audit_cell
action['context'].update({
AttributeError: 'str' object has no attribute 'update'
```
Cause:
- When clicking on a report cell, `dispatch_report_action()` calls `action_audit_cell()` of the corresponding report (Balance Sheet in this case) which in turn calls `action_audit_cell()` of `account.analytic.report`.
- When the flow reaches [1], the window action for analytic items is fetched, where its [context] is returned as a string instead of a dictionary.
- This action is then received [here] with `context` as a string, and attempting to update it results in an error.
Solution:
- Converted the string to dict using `literal_eval()`.
[1]: https://github.com/odoo/enterprise/blob/a26981667361839ad38f45da5a6f23ae8e6478f1/account_reports/models/account_analytic_report.py#L208
[context]: https://github.com/odoo/odoo/blob/824446b65cbe3850f88f56090f0473f0e94bf4f3/addons/account/views/account_analytic_line_views.xml#L88-L91
[here]: https://github.com/odoo/enterprise/blob/b5f884a49344aa097c20fc128e9d290b97970f1a/account_reports/models/balance_sheet.py#L28
opw-6311673
sentry-7513784149
Forward-Port-Of: odoo/enterprise#120734Order changes in Point of Sale are now sent to preparation displays, so kitchen or preparation teams see the latest order information without missing updates. This helps reduce confusion and keeps fulfillment aligned with what was changed at the register.
Original PR description
Before this commit, when an order change was updated, the pdis were not notified of the change. This commit adds a call to the `_send_load_orders_message` method of the pdis to notify them of the change. Forward-Port-Of: odoo/enterprise#122592
Restaurant preparation displays are now updated when a combo meal is split back into individual items, without printing duplicate kitchen tickets or triggering unnecessary alerts. The fix also ensures course labels appear on floating orders and that displays only receive items from their configured product categories.
Original PR description
Issue: Breaking a combo back into individual lines was not notifying the preparation display. Fix: breakCombo now go through sendOrderInPreparation (with byPassPrint) the preparation display is updated and no ticket is printed. To avoid triggering a sound and a kitchen ticket for a reorganization the kitchen already knows about, thread a `silent` context flag through sendOrderInPreparation down to _send_load_orders_message. Forward-Port-Of: odoo/enterprise#118690
EC Sales List returns are now generated for each company in a tax unit using that company's own VAT number, instead of combining all members under the tax unit VAT number. This helps businesses submit the correct declarations for each legal entity and avoid consolidated reporting where it is not expected.
Original PR description
Issue: The EC Sales List return is currently generated under the tax unit VAT number, consolidating all member entities into a single declaration. Expected: The EC Sales List return must be generated individually per member entity, each under their own VAT number, even when those entities belong to a tax Unit. Fix: Apply tax unit only if report's multi company filter is `tax_units`. Ref: https://github.com/odoo/enterprise/blob/07e8aba8604319747a5925c83576095ce9a63f9e/account_reports/models/account_return.py#L316-L317 task-6069402 Forward-Port-Of: odoo/enterprise#115974
Fixes Envia delivery insurance so insured shipments communicate the insurance service in the format Envia expects. This helps ensure customers using insured Envia delivery methods receive the correct insurance documentation when validating deliveries.
Original PR description
Issue ----- Insurance set on the delivery method is not correctly being communicated to Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - 10% insurance - Create a MX client - Create a product (with some weight) - Create a SO using the delivery method & confirm - Validate the picking > No insurance pdf is being printed Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#121691 Forward-Port-Of: odoo/enterprise#118966
This fix prevents small rounding differences in attendance calculations from creating overlapping overtime entries. It helps ensure employee work entries remain accurate, especially for overnight shifts or shifts ending around midnight.
Original PR description
__Issue:__ `duration` is rounded to 3 decimals (~1.8s drift) while `time_stop` is exact, so the back-projected start could land before midnight on overnight overtime or middle of the day causing overlaps with the previous line Example: - time_start = 03/05 00:00:00 - time_stop = 03/05 07:07:14 actual duration 7h07m14s gets stored as `duration = 7.121` (= 7h07m15.6s) after `round(_, 3)`. Back-projection yields `datetime_start = 07:07:14 - 7.121h = 02/05 23:59:58`, overlapping by ~2s with the prior line ending at `02/05 23:59:59.999`. __Fix:__ Sort lines by `time_stop` within each date and clamp `datetime_start` to the previously emitted interval's stop when the two intervals genuinely intersect. opw-6170828 Forward-Port-Of: odoo/enterprise#122509 Forward-Port-Of: odoo/enterprise#116565
Swiss payroll now automatically computes the required 2050 salary rule value during ELM transmission. This reduces manual payroll corrections and helps ensure Swiss salary reporting is more accurate.
Original PR description
task-5166226 Forward-Port-Of: odoo/enterprise#108047 Forward-Port-Of: odoo/enterprise#103453
The payroll payrun chatter panel and button will no longer appear in unrelated payroll views such as Time Offs. This prevents confusion by keeping payrun-specific discussion tools limited to the correct payrun screens.
Original PR description
The global `PayRunChatterService` was leaking state across shared views, causing the chatter panel and button to appear on views accessed outside the PayRun layout (e.g., via the main Payroll > Time Offs menu). Fix this by introducing a `useEffect` hook in `PayRunLayout` that checks for a valid `payrun_id` or `payRunReactive` state on view render. If absent, the chatter service state is explicitly reset and closed. The control panel button is also wrapped in a contextual `t-if` check, fully isolating the feature to its intended screens. Task : 6347871
Code cleanup and technical improvements
The Swedish SIE import tool was adjusted internally so related behavior can be extended more easily in the future. This does not introduce a user-facing change, but it improves maintainability for businesses that rely on custom accounting import flows.
Original PR description
We changed some tools to be regular model method to allow inheritance. task-none Forward-Port-Of: odoo/enterprise#121862
This update keeps the Studio view editor working reliably as the underlying web framework evolves. It replaces an outdated internal mechanism with the supported approach while preserving behavior such as restoring selected elements, keeping the sidebar in sync, and unblocking the interface after edits.
Original PR description
Replaced `useLayoutEffect` with `onMounted` + `onPatched` because `useLayoutEffect` is deprecated in OWL3. `useEffect` (OWL3's reactive effect) was tried first but caused regressions: it runs eagerly…
Replaced `useLayoutEffect` with `onMounted` + `onPatched` because `useLayoutEffect` is deprecated in OWL3. `useEffect` (OWL3's reactive effect) was tried first but caused regressions: it runs eagerly during `setup()` before mount, so `updateActiveNode`'s call to `viewRenderer.el.querySelectorAll` hit a null element. `onMounted` + `onPatched` restore the exact post-DOM-patch timing of the former `useLayoutEffect`, making the behaviour correct without any reactive-subscription machinery. `activeNodeXpath` is read inside `onPatched` but that hook is not a reactive context, so reads are naturally untracked — matching the original `untrack` wrapper. The `isInEdition` reset is written through `toRaw(viewEditorModel)` so the setter side-effect (`ui.unblock()`) still fires while no re-render is scheduled, avoiding an infinite patch loop. The `useLayoutEffect` refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - @web_studio/view_editors/form_editor/restore active notebook tab and element - @web_studio/view_editors/interactive_editor/blockUI not removed just after rename - @web_studio/view_editors/interactive_editor_sidebar/update sidebar after edition see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2602194/build/115250513
5 changes
Resolved issues and error corrections
The point of sale payment screen now only runs India-specific invoice logic when the company is actually in India. This prevents avoidable errors in automated checks and keeps the invoice toggle working reliably for other countries.
Original PR description
Toggle invoice button was making a call in IN localization even when not in a IN country. This was causing an error in runbot 940146. This commit fixes the issue by checking if the country is IN before making the call. In `pos_settle_due` the method signature was not correct.
Fixes a crash that happened when users clicked the “Restrict to User” or “Restrict to Resources” fields on appointment slots. The broken filter was removed because it did not provide useful filtering and prevented the form from working correctly.
Original PR description
Clicking the "Restrict to User" or "Restrict to Resources" field on a slot crashed with:
invalid input syntax for type integer: "appointment_type_id.staff_user_ids"
The field domain was a quoted string instead of a list, so it was passed through as a literal value. Remove the domain: it never filtered anything and only broke the form.
opw-6349497
Forward-Port-Of: odoo/enterprise#122651Blank US checks now include the same stub lines as pre-printed checks, making printed checks easier to read and process. The check bottom layout was also adjusted so blank checks fit correctly on one page.
Original PR description
See individual commits. task-6359599 Forward-Port-Of: odoo/enterprise#123144
Point of Sale now gathers Urban Piper and platform orders in one request instead of making extra sequential calls. This reduces waiting time when fetching orders and improves reliability during order synchronization.
Original PR description
Issue: pos_urban_piper overrode getServerOrders() to add a separate loadServerOrders() call for it's own orders before delegating to super, resulting in up to an additional sequential RPCs on every order fetch. Fix: Extract the base query domain into a new overridable getServerOrdersDomain() method. Each module overrides it to OR in its own domain via Domain.or([super.getServerOrdersDomain(), extraDomain]), so all orders are fetched in a single RPC call instead of three. Task-6284860 Forward-Port-Of: odoo/enterprise#122907 Forward-Port-Of: odoo/enterprise#120001
Fixed an issue where enabling FedEx return labels caused the original outgoing shipment to be treated like a return, leaving its reference field blank. Outbound FedEx labels now keep their reference information, making shipments easier to identify and track.
Original PR description
Issue ----- When setting the delivery method to create return labels aswell, the reference (`REF`) field is not present on the original outbound shipment. <img width="438" height="148" alt="image" src="https://github.com/user-attachments/assets/42acce7b-6177-4f8f-81d3-ad6dfd3e4bb2" /> Steps to reproduce ----- - Setup Fedex - Enable returns - Create a product (set weight) - Create a delivery for the product - Set carrier as Fedex - Validate delivery - Open the label > REF field is empty Cause ----- Fedex doesn't include references on the label of returns. When the option for returns is enabled, the outbound shipment is marked as a "Courtesy return". It doesn't make sense to specify a return reason on the original shipment. Expected outcome (after fix) ---- <img width="428" height="146" alt="image" src="https://github.com/user-attachments/assets/0d22e147-da90-4aa4-b3ca-2d996c7cc147" /> ----- Ticket: opw-6101620
3 changes
Enhancements to existing features
The Azerbaijani Manat (AZN) now uses its official currency symbol, ₼, instead of an older placeholder. This makes currency displays more accurate and consistent for users working with Azerbaijan-related amounts.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 Backport of: https://github.com/odoo/odoo/pull/262471 task-6112867 Forward-Port-Of: odoo/odoo#274368
Resolved issues and error corrections
This change updates an automated stock valuation test so it includes the country information required for a tax record. It helps the test suite run correctly and prevents a known runbot failure, improving build reliability.
Original PR description
Fixes runbot error [243677](https://runbot.odoo.com/odoo/error/243677)
This change avoids a rare timing issue where the same successful payment could be processed twice. It makes sure Odoo checks again before acting on a transaction, reducing the risk of duplicate order or payment handling when multiple background actions happen at the same time.
Original PR description
The following use case has been observed: 0. Customer start a payment from /shop/payment. 1. We received the webhook that notifies that the payment succeeded. 2. The payment post-processing cron…
The following use case has been observed: 0. Customer start a payment from /shop/payment. 1. We received the webhook that notifies that the payment succeeded. 2. The payment post-processing cron start (it gather all the transactions that need to be processed, including the customer new transaction) 3. Meanwhile, the customer is redirected back by the payment provider to Odoo, which then redirect to /payment/status and start the payment post-processing for that specific transaction 4. The customer initiated payment processing finishes, he is redirected back to /my/orders/... page. 5. The payment post-processing cron finally start processing the same customer transaction and process it (a second time). In that case, as the transactions to be post-processed backlog was quite high, there is consequent time between the time we gather all the TXs to post-process and actually process the customer transaction. Also we don't end up with a `SerializationError` as the cron do commit after each transaction post-processing. This commit force invalidate individual transaction cache values and recheck if it effectively still need to be post-processed before doing it. opw-6332192 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274010
1 change
Resolved issues and error corrections
This fix stops annual leave balances from receiving an unexpected extra accrual when carryover is applied. It makes accrual updates follow the intended schedule, so employees and managers see more accurate leave balances and less confusing year-start changes.
Original PR description
## Issue Currently, an extra accrual happens on carryover date, but it shouldn't. Indeed, accrual only happened at the start - end of a period, or on level transition. ## Reproducing steps Let's take an accrual plan with a level that adds 2 days/month on the 15th of the month. The carryover takes place at the beginning of the year. So we will have this: - 2025-11-01 -> creation of the allowance, 0 days available - 2025-11-15 -> 1 day (only 15 days are counted, so only half of the days are added) - 2025-12-15 -> 3 days (1 full month elapsed) - 2026-01-01 -> 4 days (as the carryover triggers an accrual) -> this event causes confusion as the accrual seems to “come out of nowhere” - 2026-01-15 -> 5 days - 2026-02-15 -> 7 days task-5432188