Friday, September 12, 2025
44 changes · saas-18.4
Resolved issues and error corrections
Printing an invoice now respects the custom PDF report configured for the customer or journal, matching the behavior already used when sending invoices. This prevents businesses from accidentally printing invoices with the generic layout when a tailored template should be used.
Original PR description
Before: Clicking 'Print' on an invoice did not respect the custom PDF report template set on the partner profile or journal. The selection was only applied in the 'Send' flow, while 'Print' always fell back to the generic invoice report. After: 'Print' now uses `_get_default_pdf_report_id()` to determine the correct PDF report. This ensures the same priority order is applied as in 'Send'. Explanation: The method `_get_default_pdf_report_id()` encapsulates the logic for choosing the report template (user → invoice default in 18.0, extended with journal in later versions). By reusing this method, we avoid duplicating logic and ensure consistency between 'Send' and 'Print'. task-5072522 Forward-Port-Of: odoo/odoo#226082
A timing issue in the point-of-sale self-order payment test was corrected so the generated self-order link includes the required access token. This keeps kiosk QR code payment validation reliable and prevents failures related to IoT payment channel setup.
Original PR description
A call to `_get_self_order_route` in the `test_online_payment_kiosk_qr_code` test was happening too early, resulting on getting the self order url missing the `access_token`. This resulted in making the test fail due to the override of the `iot_http` service in `pos_self_order_iot`, relying on this token to get the IoT WebSocket channel. Enterprise PR: odoo/enterprise#93895
Checkout payments using saved payment methods are now held until the order has passed final validation. This prevents customers from being charged when a last-minute issue, such as an expired coupon, stops the order from completing.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have a saved Stripe payment token; 2. create a discount coupon program & a coupon; 3. go to /shop & add a product to your cart; 4. go to checkout; 5. apply coupon; 6. before finalizing payment, set coupon program expiration to yesterday; 7. finalize payment. Issue ----- An error appears, because of the reward change, but a payment request has already been sent. Cause ----- For token transactions, `_send_payment_request` is called immediately upon creation, i.e. before the `WebsiteSale` controller is able to validate the transaction using `_validate_transaction_for_order`. Solution -------- If the payment flow happens via token, add a `delay_payment_request` context value. When creating a token transaction in `PaymentPortal`, only call `_send_payment_request` if this value is not set in the current context. opw-5013284 Forward-Port-Of: odoo/odoo#226067 Forward-Port-Of: odoo/odoo#225008
Preparation tickets in Point of Sale now include customer notes added to individual order lines. This helps kitchen or preparation staff see specific customer requests directly on the ticket, reducing missed instructions and order mistakes.
Original PR description
In this commit: ----------- Orderline-level customer notes are now printed on preparation tickets. Task-4879140 Related: https://github.com/odoo/enterprise/pull/90229 Forward-Port-Of: odoo/odoo#226382 Forward-Port-Of: odoo/odoo#215761
Sales orders created from a contact now use that contact’s preferred delivery address, matching the behavior in the Sales app. This prevents orders from being sent to an older or unintended address when customers have multiple delivery locations.
Original PR description
## Versions 17.0+ ## Issue When creating a SO from the Contacts app, the first delivery address is used, ignoring the preferred one. In contrast, the Sales app correctly uses the preferred delivery…
## Versions
17.0+
## Issue
When creating a SO from the Contacts app, the first delivery address is used, ignoring the preferred one. In contrast, the Sales app correctly uses the preferred delivery address. This fix ensures consistent behavior across both.
## Steps to reproduce
*Ensure Contacts app is installed*
*Activate "Customer Addresses" in the settings*
- Go to the Contacts app:
- Create a new contact:
- Name: C1;
- Contacts & Addresses:
- Delivery Address (Add 2 new addresses):
- D1;
- D2.
- Click the "Sales" action button:
- Create a new SO for C1 (pre-filled):
- Invoice Address: C1, D2;
- Delivery Address: C1, D2;
- Add any product with:
- Quantity: 1;
- Delivered: 1.
- Create the invoice and confirm it.
- Go back to Contacts and look for C1:
- Click the the "Sales" action button:
- Create a new SO and see the Delivery Address set to "C1, D1".
- Go to Sales app:
- Create a new SO and select C1 as customer;
- Delivery Address retrieves "C1, D2" as it is the preferred address.
## Cause
Each time an invoice is validated, the corresponding address gets a higher score.
This score is then used in the SQL ordering of customers/suppliers:
https://github.com/odoo/odoo/blob/b523f5c6d8e235a6cedb029f701a0ebd89a5f74a/addons/account/models/partner.py#L347-L354
## Fix
Apply context search mode if first call. This mimics the base behavior: https://github.com/odoo/odoo/blob/b57bb1decd46dcbb1fe602bb72b6f8e5382e9b28/odoo/addons/base/views/res_partner_views.xml#L534
opw-4916381
Forward-Port-Of: odoo/odoo#225189This fix prevents a closed websocket connection from being treated as an unexpected internal error during test handling. It restores the intended cleanup behavior, reducing confusing error reports and improving reliability in core infrastructure.
Original PR description
Followup to 16.0-closed-in-stop-xmo: the condition in `stop` is a `hasattr`, so we need to delete `self.ws` not set it to `None`. Setting it to `None` means the condition passes then blows up as soon as we try to use it, which means we "just" converted all the old `WebSocketConnectionClosedException` to an `AttributeError`. https://runbot.odoo.com/odoo/error/231446 Forward-Port-Of: odoo/odoo#226267
Fixes an issue where users returning from an external link in a dashboard were taken back to the first dashboard instead of the one they had selected. This preserves the user’s place and avoids confusion when navigating between dashboards and linked pages.
Original PR description
Steps to reproduce: - go to dashboards - select a dashboard with external links on scorecard charts for instance (do not select the first dashboard) - click on the chart w/ the external link to be redirected - Go back to the previous page through the browser The selected dashboard is now the first dashboard instead of the one you came from. the behaviour was broken since the introduction of the path-based routing in #157867 as we did not specify a path for the dashboard action but still worked because the action params were sent in the context but this was corrected in #216067 task-5067826 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
Fixed an issue in restaurant Point of Sale where combo items could lose their connection to the main combo product after an order was synchronized. This helps staff return to a table and continue editing orders without combo meals appearing as separate regular products.
Original PR description
When one of the combo line is marked as "Dirty", it would be synched but it would remove it's link to the combo parent. Steps to reproduce: ------------------- * Create a combo product * Open a PoS restaurant * Open a table, and add the combo product * Leave the table to synchronize the order with the backend * Go back on the table and select a partner * This will mark the combo line as "dirty" * Leave the table again to synchronize the order with the backend * Go back on the table > Observation: The combo now appears as a normal product, not linked to the combo parent. Why the fix: ------------ When marking a line as "dirty", we now make sure to also mark it's combo parent as "dirty" so that it will be synchronized correctly. And keep the link to the combo parent. opw-4950262 Forward-Port-Of: odoo/odoo#225573 Forward-Port-Of: odoo/odoo#220099
Users can now update approvers on their own approval requests without running into an access error. The change also prevents request owners from adding, editing, or deleting approvers when they should not have that permission, improving consistency and control in the approval process.
Original PR description
Fixed an issue happening when trying to add approvers to one's own request, and remove their ability to delete approvers from the request Task-4897775 Forward-Port-Of: odoo/enterprise#94261 Forward-Port-Of: odoo/enterprise#92309
Due to time constraints the translations were not added in the commit adding the modules (72ac059edfcc35ad44c5faa9daf971123377af24). This commit adds the translations / fills the `.po` files. The translations were created by LMAN based on the 18.0 po files. Veri*Factu task: task-3745982 Forward-Port-Of: odoo/odoo#226298 Forward-Port-Of: odoo/odoo#225173
Original PR description
Due to time constraints the translations were not added in the commit adding the modules (72ac059edfcc35ad44c5faa9daf971123377af24). This commit adds the translations / fills the `.po` files. The translations were created by LMAN based on the 18.0 po files. Veri*Factu task: task-3745982 Forward-Port-Of: odoo/odoo#226298 Forward-Port-Of: odoo/odoo#225173
The cash basis General Ledger now combines duplicate payment-related entries before showing additional results. This prevents errors when users load more lines for accounts with many payments, making financial reporting more reliable.
Original PR description
**Steps to reproduce:**: - Install the module "account_reports_cash_basis" - Create a new account - Create an invoice with a line in the newly created account - Create a number of payments on the…
**Steps to reproduce:**: - Install the module "account_reports_cash_basis" - Create a new account - Create an invoice with a line in the newly created account - Create a number of payments on the invoice - Go to general ledger, and set method to cash basis - Set limit to a value less than the number of payments - Open the account on the general ledger, and click on load more **Issue:** After clicking on 'Load more', we get a traceback due to duplicate lines **Cause:** The same aml can return multiple results when using "account_reports_cash_basis" module. While this has been taken into consideration for each batch of lines loaded into the report (we won't get the same line referenced two times in the same batch, since they are grouped together), if we load a new batch by clicking "Load More", we can potentially get a line that was referenced in the first batch, and we get an error for having two lines in the report referencing the same thing. **Solution:** We add a add a GROUPBY statement in the query of _get_aml_values() This will add up all the cash basis lines in the query itself. opw-4635115 Forward-Port-Of: odoo/enterprise#93904 Forward-Port-Of: odoo/enterprise#86817
This fixes an issue where service lines added after a sales order was confirmed showed a zero cost instead of the product's configured cost. The correction helps keep margins accurate when teams update confirmed sales orders with additional services.
Original PR description
…O confirmation **Problem:** When a service is added on a SO after the confirmation the cost column (purchase_price) is 0 **Steps to reproduce:** - make sure that sale_timesheet_margin is installed - create a service with a positive cost - create a SO for 1 unit of this service - confirm - add a new line on the SO for the same service **Current behavior:** the cost is 0 **Expected behavior:** the cost should be the cost you set on the product form **Cause of the issue:** since this PR https://github.com/odoo/odoo/pull/207228 services that are "ordered_prepaid" on confirmed sale order are filtered out the purchase price computation https://github.com/odoo/odoo/blob/5f6d2afa8c09fe72c01d056ebef01214567a4a99/addons/sale_timesheet_margin/models/sale_order_line.py#L9-L15 opw-5016622 Forward-Port-Of: odoo/odoo#225704 Forward-Port-Of: odoo/odoo#225027
This update adjusts an internal email server test to match a changed error message from a supporting mail library. It helps keep automated quality checks reliable without changing how users work with Odoo.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226489
This update fixes failing automated tests in the online shop area. It helps keep the website sales feature reliable by ensuring test checks run successfully during validation.
Original PR description
runbot-error-227575 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Payments for Mexican electronic invoices could fail validation when an invoice was issued in a foreign currency and paid in MXN because exchange-rate rounding was handled inconsistently. This fix aligns the calculation with the official rounding rules, helping affected payments validate correctly and reducing manual correction work.
Original PR description
Steps to reproduce: - With an MX Company setup - Set USD rate to: - 0.049216958195 for day 1 - 0.053418803419 for day 2 - Create an invoice in USD as follows: - line 1: price_unit 91, quantity 64,…
Steps to reproduce:
- With an MX Company setup
- Set USD rate to:
- 0.049216958195 for day 1
- 0.053418803419 for day 2
- Create an invoice in USD as follows:
- line 1: price_unit 91, quantity 64, tax 16%
- Confirm and send CFDI
- Register full payment in MXN
- Send Payment CFDI
Issue: Payment validation will fail with error
Code : CRP20268
Message : El campo BaseP que corresponde a Traslado, no es igual a la suma de
los importes de las bases registrados en los documentos relacionados donde el
impuesto del documento relacionado sea igual al campo ImpuestoP de este elemento
y la TasaOCuotaDR del documento relacionado sea igual al campo TasaOCuotaP de
este elemento.
Message : Valor esperado: 109025.275956 valor reportado: 109025.275862
This occurs because the precision set in https://github.com/odoo/enterprise/commit/e642e4d6d35c79d02c799d12451f3e2d92ab96e9 is high and can lead to failed
verification due to rounding on our side, because we compute BaseP using
the full digits of EquivalenciaDR, but, according to the specs, we
send it rounded to 10 digits.
opw-4750981
Forward-Port-Of: odoo/enterprise#94465
Forward-Port-Of: odoo/enterprise#92768The survey leaderboard now shows score changes in a clearer sequence, so participants can better understand how their points are updated after each question. The leaderboard display was also enlarged to prevent scores from appearing cramped or incorrectly shown.
Original PR description
The way the score bars were animated was a bit confusing. We simplify the animation by: - Showing the score accumulated so far without the question - Animating the score bar towards the accumulated…
The way the score bars were animated was a bit confusing. We simplify the
animation by:
- Showing the score accumulated so far without the question
- Animating the score bar towards the accumulated score with the question
- Animating the numerical score on the left towards the accumulated score with the question while fading the numerical score increment on the bar ("+ x p")
- (reordering participants)
We also fix the size of the leaderboard as it was too small to display the score correctly.
How to reproduce
- Create a scored survey with time reward
- Add a question to get the name and toggle the nickname option
- Add a question with an answer that grants n points
- Start a live session
- After a user has completed the question
- Display the leaderboard
The score animation is confusion as it was going through:
- Showing the score accumulated so far without the question
- Animating towards 0: showing a minimal bar due to the minimum size of the score bar
- Animating towards the score question (on top of the minimal bar)
- And finally adding the score accumulated so far without the question
Task-4893763
Forward-Port-Of: odoo/odoo#224996This fix makes the website editor's background positioning tool align correctly with the selected section across scrolling, mobile preview, browser zoom, and scroll effects. Users can now adjust background images more consistently without missing overlays, blocked scrolling, or misleading loading masks.
Original PR description
__Current behavior before commit:__ The background position overlay action allows the user to move the background image of the editing element. To do that it copies it inside an overlay which is…
__Current behavior before commit:__ The background position overlay action allows the user to move the background image of the editing element. To do that it copies it inside an overlay which is outside the iframe since the [Website refactoring]. This creates multiple challenges because the overlay needs to perfectly align with the editing element behind it which is not a trivial task for several reasons: - The iframe can have different sizes and positions when toggling the mobile preview. - The editing element can be anywhere on the page, and it can move if the user scrolls. - Some scroll effects depend on the dimensions of the viewport which is different in and out of the iframe. Furthermore the `overlay` plugin currently used is designed for contextual menus and pop-ups. It forces the overlay content to always be fully visible in the window and it hides the content if it is bigger. This makes it unsuitable for the purpose of positioning a background image. Here are several bugs that arise from the above: - The overlay doesn't appear if the editing element is taller than the window. - When the overlay is open, it's only possible to scroll while the mouse is hovering the scrollbar. - The overlay image doesn't follow the editing element after scrolling. - The overlay dark mask doesn't cover the whole iframe window. - The loading spinner and its dark overlay is displayed while the background position overlay is on. - If the Scroll Effect is set to "Zoom Out" with maximum intensity, the overlay is not correctly positioned. - If the Scroll Effect is set to "Fixed", the overlay **is** correctly positioned but the background position doesn't align with the one behind it. - In the mobile preview the overlay doesn't cover the iframe. - etc. __Description of the fix:__ Several things are now done differently to fix these issues: - The `overlay` service is used instead of the plugin. This way we have a better control over the positioning of the overlay. - The overlay positioning is more robust to take into account the mobile preview iframe position, the page scrolling and a possible browser zoom. - We stop using an image copy, instead the editing element `background-position` is directly modified making it a perfect wysiwyg. To do this, the overlay dark mask is kept but the portion in front of the editing element is cut-out to highlight it. An invisble dragger element is there to be able to listen to mouse event for the dragging. Also, the content of the section is made invisible so that only the background is shown. [Website refactoring]: https://github.com/odoo/odoo/pull/187419 Related to task-4367641
The Documents app now consistently shows the Activities button in the document chatter, including for files linked to other document-related models such as signing documents. This makes it easier for users to manage follow-ups and tasks from the same place without missing activity options.
Original PR description
Step to Reproduce: - Install `Documents_sign` module - open Documents - click on 'info & tags` button on the top right corner to show chatter - Open 'Odoo CLA.pdf' document Observation: - The Activities button is not shown in Chatter. Issue: - after this https://github.com/odoo/enterprise/commit/a32825ee00f2b330d99113f4d8c1488903fe744e, the activities button shows only for those documents which are related to `documents.documents` model or a document has no model, but it should be shown for all documents https://github.com/odoo/enterprise/blob/23fb26ae0f91a5bdb74d0d4fce48b31fa7abef86/documents/static/src/views/kanban/documents_kanban_renderer.xml#L21-L26 Solution: - Remove condition for Kanban and list view to show `activities` button in Chatter opw-5013427 Forward-Port-Of: odoo/enterprise#94361 Forward-Port-Of: odoo/enterprise#93093
The web test runner now reports critical setup problems during dry runs as real errors. This helps Odoo’s automated checks catch blocking test issues earlier and more clearly, reducing the risk of failed or misleading test runs.
Original PR description
The test runner replaces most occurences of `console.log` with a formatted `console.trace`, as to avoid duplicate runbot error messages in general. The issue is that during the dry run, errors that are caught should be logged on the runbot since these errors are more critical (i.e. duplicate test name, which will prevent the runner to run at all). This commit ensures that errors caught during dry run are logged as actual errors to prevent this issue. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225688
The web test runner now avoids over-simplifying test URLs when specific tests are excluded. This keeps automated test selections accurate, reducing the risk of running the wrong set of tests during development and validation.
Original PR description
Before this commit, when the test runner simplified the URL (e.g. if the runner is given the ID of every test in a suite, it will remove them and only include the suite ID), it always considered IDs as being "included", and ignored the "-" specifying that some IDs should be "excluded". --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225950
This fix makes the online rental checkout test wait until the cart has fully updated after a customer changes the rental duration. It helps prevent false build failures and improves confidence that rental pricing is displayed correctly before checkout checks continue.
Original PR description
steps to reprduce: 1. duplicate multi enterprise 18.0 database 2. run the tour `website_sale_change_rental_duration` in the duplicated database inspired from: https://github.com/odoo/enterprise/commit/c7542e897c537650966497065db9c7d033dcb8ee added a delay to wait when choosing the rental duration, after page is loaded when go to cart , check if the next page is loaded before checking untaxed amount build_error-227718 Forward-Port-Of: odoo/enterprise#93659 Forward-Port-Of: odoo/enterprise#89274
Survey datetime answers now show the same time in list views and detail forms by using the current user's timezone. This prevents confusion when reviewing submitted survey responses across different time zones.
Original PR description
Steps to reproduce ==================== 1. Create survey with some datetime questions. 2. Receive some response on it. 3. Check answer of datetime questions in answer tab. 4. Click on that answer to open form. ->The time shown in answer tab differs from actual value in form. The display_name of survey.user_input.line is computed based on the answers submitted by users. For questions of type datetime, the display_name was generated by converting the datetime value to a string without accounting for the user's timezone, leading to a mismatch between the actual value and the displayed time. After this commit ================== This commit updates the computation of display_name for datetime answers to consider the current user's timezone. Task-4890423 Forward-Port-Of: odoo/odoo#226354 Forward-Port-Of: odoo/odoo#216281
This fix prevents inserted non-editable blocks, such as banners or tables of contents, from blocking full-content deletion in the HTML editor. It adds a blank paragraph before those blocks so users can reliably select all content and delete it, avoiding frustrating editing leftovers.
Original PR description
**Current behavior before PR:** If the first child of an editable element was `contenteditable="false"`, selecting all content and pressing backspace would not remove everything. This was due to a Chromium bug where non-editable elements as the first child are not fully selected. **Desired behavior after PR is merged:** When inserting elements such as a banner or table of contents, a paragraph is added before them. This ensures that the editable element never starts with a non-editable child. task: 5010666 Forward-Port-Of: odoo/odoo#223357
This fix prevents the website editor from crashing when users edit links in mega menus and when removing formatting from styled buttons. It makes formatting cleanup safer so business users can edit navigation and buttons without unexpected errors.
Original PR description
Description of the issue this PR addresses: Issue 1: Steps to Reproduce: - Open the website. - Create a mega menu. - Enter edit mode. - Change the mega menu template to “Cards”. - Click on any option…
Description of the issue this PR addresses: Issue 1: Steps to Reproduce: - Open the website. - Create a mega menu. - Enter edit mode. - Change the mega menu template to “Cards”. - Click on any option available in the mega menu. - A link popover will open. - Click the Edit link button in the popover. - Click the Apply button to save the link. - A traceback occurs. The error occurs because the text-wrap class is applied to the link. When the hasColor method is triggered, it checks whether a.nav-link has a text color class. However, TEXT_CLASSES_REGEX incorrectly matches text-wrap as a color class. As a result, the removeColor method attempts to remove it and triggers _applyColor to remove the color, but in _applyColor method it does not find any color to remove on selected text. As a result, the removeColor process enters an infinite loop, which eventually leads to a traceback. Solution: Update TEXT_CLASSES_REGEX so that it only matches valid text color classes and excludes formatting classes such as text-wrap, text-center, etc. Issue 2: This commit ensures that the remove format action is disabled when a button (.btn element) has custom color or background color applied. Because buttons include padding, there is no proper way to remove a background color from a partially selected button, so the action must be ignored in this case. task-5062715 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226369 Forward-Port-Of: odoo/odoo#225477
This fix prevents online orders from being confirmed when items have gone out of stock, even if a gift card covers the full payment. It closes a checkout loophole so inventory rules are enforced consistently across payment methods.
Original PR description
In this bug, when a order is out of stock, it can be validated if gift card is used as the sole method of payment. This happens when a product gets out of stock while it is on customer's cart. The…
In this bug, when a order is out of stock, it can be validated if gift card is used as the sole method of payment. This happens when a product gets out of stock while it is on customer's cart. The other payment methods fail successfully but if gift card is used, the order can be validated. To reproduce: 1- Create a product and add quantity on stock. 2- Uncheck `Conitnue Selling` in `Out-of-Stock` 3- Publish the product on the website 4- Create a gift card 5- Add the product to the cart using portal user 7- Using admin user, set the quantity to less than ordered quantity 8- Using portal user, proceed to payment, and use the gift card. Then checkout. 9- As you see, the order is validated The issue is because `_check_cart_is_ready_to_be_paid()` which is supposed to check the stock, is only called inside `shop_payment_transaction()`. However, when checking out with gift card, this method is not called. To solve the issue, we can call `_check_cart_is_ready_to_be_paid()` also inside payment validate flow. However this only be called when a gift card is used solely. (The case `order.amount_total` is 0) opw-4941658 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226394 Forward-Port-Of: odoo/odoo#222306