Thursday, April 17, 2025
21 changes · 17.0
Enhancements to existing features
This change adds a customization point for the sales product configurator dialog. It lets extensions adjust dialog settings without replacing core behavior, reducing maintenance effort and upgrade risk.
Original PR description
**Description of the issue/feature this PR addresses:** Introduce a hook method to be able to override the ProductConfiguratorDialog props, as there's no other way to extend it otherwise. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Accounting entries created from CodaBox imports now keep the original received CODA or SODA file as an attachment. This makes it easier for businesses to audit, verify, or share the source document behind each generated entry.
Original PR description
It's always useful to keep the original .coda or .xml (for SODA) file that we receive from CodaBox on the created entry. task-none
Resolved issues and error corrections
Refund invoices created after a product return now preserve the sales team from the original sales order instead of replacing it with a default team. This keeps sales reporting, ownership, and follow-up aligned with the correct team.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Create a sales order with a deliverable product; 2. set sales team to a team you're not a member of; 3. validate the delivery; 4. create & confirm an invoice…
Versions -------- - 17.0+ Steps ----- 1. Create a sales order with a deliverable product; 2. set sales team to a team you're not a member of; 3. validate the delivery; 4. create & confirm an invoice for the order; 5. via the delivery form, create & validate a return delivery; 6. create a new invoice for the order. Issue ----- The sales team on the initial invoice is the same one as on the order. The sales team on the second invoice is changed to a default value. Cause ----- The `team_id` gets recomputed on a `move_type` change. The reason the `move_type` changed after creation, is because the `_create_invoices` method first wants to have the final total of the invoice before deciding whether it should be an `out_invoice` or an `out_refund`: https://github.com/odoo/odoo/blob/d7af5c443b03c18e364a74571560b3583969c1d7/addons/sale/models/sale_order.py#L1401-L1407 Solution -------- Knowing that the `action_switch_move_type` method could recompute the `team_id`, protect the field when calling it in `_create_invoices`. opw-4563006
Miscellaneous changes
Despite #205190 we still have sometimes a broken cursor, most of the time because of a websocket request. This is because this stable solution cannot catch a cursor without cookie that is executed after the browser closes, or during the next test. Checking the logs: 2025-04-11 05:18:04,048 13 INFO 78181227-16-0-all odoo.tests.common: Opening a test cursor without specified test on request /websocket in /knowledge/tests/test_knowledge_form_ui.py:TestKnowledgeUI.test_knowledge_main_flow 20
Original PR description
Despite #205190 we still have sometimes a broken cursor, most of the time because of a websocket request. This is because this stable solution cannot catch a cursor without cookie that is executed…
This change relocates a manufacturing subcontracting test to the purchase-related subcontracting module where its required behavior is defined. It helps keep automated checks reliable and prevents false test failures when modules are tested independently.
Original PR description
moving it to the module mrp_subcontracting_purchase is the correct module, as it depends on the override of _get_resupply_availability happening in mrp_subcontracting_purchase module accorinding to this PR (https://github.com/odoo/odoo/pull/144702/files#diff-54bc40f604ca24cec75d6f7473d21d1d2d0300576456026fe63164daf7cd5149) and fails as a single app test in mrp_subcontracting build_error-163126
This update fixes timing issues in automated checks for the sales product catalog. It helps prevent false test failures, improving confidence in release validation without changing day-to-day user behavior.
Original PR description
The test introduced in 5734ba9 opens the product catalog, filters it, then adds a product and updates its quantity. The problem is that when the product is already visible in the catalog (before filtering), the next steps can be triggerred while the filtering is still being processed. Once the filtering is done, the state of the product in the catalog is "reverted" to how it was when the filtering was called. This might be inconsistent with the state expected by the step the tour is currently in. We can solve this by adding a different product to be filtered out. This allows to add a blocking step that just waits for the catalog not to include the new product. Fixes runbot errors: [162099](https://runbot.odoo.com/odoo/error/162099) [163417](https://runbot.odoo.com/odoo/error/163417)
Long requirement text in CRM kanban stage tooltips now wraps instead of overflowing off the screen. This keeps stage guidance readable and prevents layout issues when users enter longer formatted text.
Original PR description
<b>Steps to produce:</b> 1) Install CRM 2) In debug mode, open the stages from the crm configuration 3) Give a long text to Requirements with spaces to the stage 'new' 4) Now open my pipeline and hover on the new stage <b>Issue:-</b> When the user gives a long text with spaces to the requirements in the first stage, It is overflowing the screen. <b>Solution:-</b> Add the class text-prewrap to the tooltip of the kanban header. So the "formatted text" is respected for the kanban stage. opw-4623639
This fixes an issue in the website editor where a section hidden on desktop could disappear while editing after the user temporarily forced it visible. Editors can now continue working without losing sight of hidden content they intentionally chose to display.
Original PR description
Steps to Reproduce : - Drag and drop a "Text" snippet. - Click on "Hide on desktop". - Toggle on the eye button to force its visibility. - Click on a text outside the snippet & press enter. - Bug: the invisible snippet disappears. The issue comes from the fact that when we press Enter, a new paragraph is created and a history rollback is triggered at that moment. So when we go back in the history because of that rollback, the invisible snippet loses the "o_snippet_override_invisible" class that had just been applied. Actually, adding and removing this class should not be inside the observer. This commit prevents that from happening. task-4690318
This fix prevents Odoo from sending duplicate Date or Server headers in certain web responses. It reduces unnecessary server warning messages without changing normal user-facing behavior.
Original PR description
Werkzeug historically prevented sending the same header twice[^1] but a refactor done with Werkzeug 2.0.0 removed that code[^2]. Additionnally `http.server.BaseHTTPRequestHandler.send_response`[^3]…
Werkzeug historically prevented sending the same header twice[^1] but a refactor done with Werkzeug 2.0.0 removed that code[^2]. Additionnally `http.server.BaseHTTPRequestHandler.send_response`[^3] always send both the `Server` and `Date` header, no matter if those headers are actually present in the response already. The Werkzeug team is aware (issue 2500) of this issue but they considere **rightfuly** that (1) we shouldn't be using their builtin http server, and (2) that it is a problem to be solved upstream in CPython. We usually don't send those two headers, and let werkzeug/http.server send them for us. But when using `Response.make_conditional`, Werkzeug is gonna force a Date header with the response. This is desirable because the Date is very when doing conditional requests, as the resource might have been created in the past but be still fresh. The result is that when using `Response.make_conditional`, there are 2 Date headers in the response. This is not a problem when the two Date headers have the same value, but nginx is still sending warnings. The operational team here at Odoo wants to get rid of those silly warnings. In this work we silently discard the second Date/Server header in case it has the same value as the first one. And we emit a warning may those two values be different. Note that the header that is discard is the one from the response, and not the one that http.server always send with `send_response`. Ideally we should do the contrary: discard the one of `send_response` and keep the one from the response, but that's more complicated, and we don't need it at the moment. [^1]: pallets/werkzeug:37b3fcc [^2]: pallets/werkzeug:d062807 [^3]: https://github.com/python/cpython/blob/f1967e72498209e42f7cf5eeff0cd84d1ec10d18/Lib/http/server.py#L499-L510 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
The POSBox homepage can now show certificate status messages that are not errors in the advanced view. This avoids alarming users with error-style messaging when the certificate information is only informational or otherwise non-critical.
Original PR description
This commit is a backport of commit 1f761a3. The original commit message follows: Certificate banner in "advanced view" on the homepage could only display an "error" message, even when the message was not an error. This is not the case anymore. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Tasks created from service products now keep their connection to the related sale order even when project billing is turned off. This restores the sale order shortcut on those tasks, making it easier for users to trace work back to the customer order.
Original PR description
When billing is disabled for a project, tasks created for service products in a sale order do not have their `sale_order_id` set. This is because the `_compute_sale_order_id` method explicitly skips assigning a sale order when `allow_billable` is False. Current behavior before PR: There is no smart button linking back to the sale order on the task since len(sale_order_id) == 0 Desired behavior after PR is merged: The sale_order_id is still set when the task.allow_billable == False. Steps to reproduce: 1.) Create a project with the Billing config disabled 2.) Create a service product that creates a task on order within the project from step 1 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Website popups with short display delays now reappear after the configured waiting period instead of being hidden for the rest of the browser session. This keeps promotional or informational popups aligned with the timing set by site managers.
Original PR description
Steps to reproduce the issue: - Add a popup with a 0.0001 days config. - Visit the page as a non-connected user. - The popup opens at some point. - Close the popup. - Wait 10 seconds. - Refresh the…
Steps to reproduce the issue: - Add a popup with a 0.0001 days config. - Visit the page as a non-connected user. - The popup opens at some point. - Close the popup. - Wait 10 seconds. - Refresh the page ---> The popup never reappears. This issue comes from the fact that we were setting a non-integer value for the cookie expiration. The "max-age" attribute does not accept float values, so the cookie is treated as a "session" cookie. It only expires when the session ends, which can be effectively "never" on some browsers that keep sessions open indefinitely. This used to work before commit [1] because we were also setting an "expires" attribute. When the "max-age" attribute was invalid, the browser would fallback to the "expires" attribute. Since that commit removed the "expires" attribute, the only remaining value (max-age) is invalid, and the popup never reappears as expected. This fix ensures the value used in "max-age" is always an integer, avoiding any invalid cookie behavior. [1]: https://github.com/odoo/odoo/commit/006ee1fc470eabdcbde68077259cf543633d6490 task-4690318
Invoice reports for Chile now show the percentage sign on tax lines. This prevents confusion when customers or accountants review VAT amounts on printed or exported invoices.
Original PR description
The percentage sign is missing on the tax line in the invoice report opw-4661577
This fixes a website newsletter signup issue that could occur when Cloudflare Turnstile was not installed. The page now avoids a script error, helping visitors subscribe smoothly even without that optional protection enabled.
Original PR description
When Turnstile was not installed, JS would try to deconstruct an undefined value, resulting in an error. Introduced in: https://github.com/odoo/odoo/pull/200158/files :see_no_evil: opw-4625786
Odoo Studio now prevents users from opening advanced options for certain system-managed fields that cannot be edited. Instead of triggering an error, users see a clear dialog explaining that these field properties are unavailable.
Original PR description
Steps: - Install `web_studio` - Enable debug mode - Open Users view - Open studio - Select any users fields (Users Types for example) - Click on More - Traceback Similar fix: https://github.com/odoo/enterprise/pull/50249 https://github.com/odoo/enterprise/pull/60321 This commit add a dialog preventing the users from accessing fields properties. opw-4700432
This fixes Chilean invoice reports so tax lines correctly show the percentage sign. It helps customers and recipients read VAT amounts clearly and reduces confusion in official invoice documents.
Original PR description
The percentage sign is missing on the tax line in the invoice report opw-4661577
This fix allows WhatsApp message templates to keep or receive the intended account during import or setup. It prevents templates from being forced to the automatically selected account, helping businesses manage templates across multiple WhatsApp accounts correctly.
Original PR description
In [1] we added a compute on wa_account_id in stead of a default to allow for a smarter default. We forgot to mark the field readonly in the process. This prevents the import of existing templates, or of templates from different accounts. task-4734669 Correction for: task-4369979 [1]: 7a593a4aa5040998dc12468dec12dca62f573030
Despite #205190 we still have sometimes a broken cursor, most of the time because of a websocket request. This is because this stable solution cannot catch a cursor without cookie that is executed after the browser closes, or during the next test. Checking the logs: 2025-04-11 05:18:04,048 13 INFO 78181227-16-0-all odoo.tests.common: Opening a test cursor without specified test on request /websocket in /knowledge/tests/test_knowledge_form_ui.py:TestKnowledgeUI.test_knowledge_main_flow 2025-04-11 04:56:57,155 13 INFO 78181121-16-0-all odoo.tests.common: Opening a test cursor without specified test on request /websocket in /test_sale_product_configurators/tests/test_sale_product_configurator.py:TestProductConfiguratorUi.test_02_product_configurator_advanced That indicates that we are in the case where the request don't have a cookie, despite the route being called from a chrome. It is most likely due to the fact that the browser cookie are cleared at the end of a browser js call, before navigating to about:blank 2025-04-11 04:56:57,119 13 INFO 78181121-16-0-all odoo.addons.test_sale_product_configurators.tests.test_sale_product_configurator.TestProductConfiguratorUi: Deleting cookies and clearing local storage It is actually easy to reproduce by adding a sleep before navigating to about:blank in browser.clear(). We can see that the websocket route is still called periodically at the end of a test. This error will occur when this request is made just between the cookies are cleared and the page navigates to about:blank. In 16.0, some modifications where made regarding cookie cleanup order. After 17.0 since the browser is closed, waiting for the browser to close instead Another possibility is to check if the request is a websocket request and to not open a cursor in that case if we don't have a cookie identifying the test. This cannot be done for all requests since it is possible that some call are made when generating a pdf, or any call that would open a TestCursor without being inside a browser_js or url_open Combining both solution should hopefully highly reduce this error. A final decision was made to also forbid any request coming after a browser_js. - browser_js is the main source of request reaching the server asynchronously. Other ways to create a request on the server is synchronous with the test and will wait for the result. - After a browser js, it is unlikely to make another request outside an url_open or browser_js. It was the case for some xmlrpc requests, the dirty solution was to make the test non strict during this request. Those tests could still be a small cause of randomness. Forward-Port-Of: odoo/odoo#206006
Steps to reproduce: 1. Drag and drop a popup snippet. 2. Add a banner inside the popup snippet. 3. Set the banner to be invisible on desktop by selecting `no_desktop` visibility on the `Block` element. Issue: The popup remains open, but the element is incorrectly marked as hidden in the invisibility elements list. Solution: This PR ensures that the element's visibility is toggled correctly and triggers the snippet activation to false. task-4337481 Forward-Port-Of: odoo/odoo#187233
Original PR description
Steps to reproduce: 1. Drag and drop a popup snippet. 2. Add a banner inside the popup snippet. 3. Set the banner to be invisible on desktop by selecting `no_desktop` visibility on the `Block` element. Issue: The popup remains open, but the element is incorrectly marked as hidden in the invisibility elements list. Solution: This PR ensures that the element's visibility is toggled correctly and triggers the snippet activation to false. task-4337481 Forward-Port-Of: odoo/odoo#187233
# Context: A recent improvement (https://github.com/odoo/odoo/pull/203739) slightly changed how the search domain for `ancestors` operates. Before it ignored note subtypes, i.e. `'subtype_id', '!=', note_type.id`. After the PR, it now matches all messages as long as they have a subtype. In doing so, it didn't account for the fact that in some production database, you might have `mail.message` records that have **no** message_id set, i.e. `message_id == False`. In such cases a traceba
Original PR description
# Context: A recent improvement (https://github.com/odoo/odoo/pull/203739) slightly changed how the search domain for `ancestors` operates. Before it ignored note subtypes, i.e. `'subtype_id', '!=',…
# Context:
A recent improvement (https://github.com/odoo/odoo/pull/203739) slightly changed how the search domain for `ancestors` operates. Before it ignored note subtypes, i.e. `'subtype_id', '!=', note_type.id`.
After the PR, it now matches all messages as long as they have a subtype.
In doing so, it didn't account for the fact that in some production database, you might have `mail.message` records that have **no** message_id set, i.e. `message_id == False`.
In such cases a traceback would be generated when sending a message from a mail.thread having an ancestor without `message_id` set.
Example:
```
references = ' '.join(m.message_id for m in (ancestors + message_sudo))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: sequence item 1: expected str instance, bool found
```
While such records *should* not exist when using the ORM, they might be the result of:
* certain upgrade scripts that use direct SQL (cf https://github.com/odoo/upgrade/blob/06b9e7f3cd98c383698695d6028bb7adefb6f805/migrations/base_vat/saas~16.3.1.0/pre-migrate.py#L104-L120)
* direct SQL inserts by users or/and customisations
# Proposed solution:
Since there are no ad-hoc mecanismes to fix such records on productions, the next best thing would be to simply adapt the search domain for `ancestors` and ignore any records where `message_id == False`. Indeed, if there is no `message_id` it makes no sense to try to add it in the references header.
# Reproduction steps:
1) Setup database and install contacts
2) Pick a contact and post a log note
3) For this new `mail.message` write `message_id == False` in the backend 4) Try to send a new message to the contact
-> Traceback
OPW-4728399
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#206279This PR introduces a regression test to ensure that the sitemap remains in the default language of the website, regardless of the language version being accessed. Tests 2 scenarios: - First, configure a website with English and French language. - Set the default language to French. - Access the sitemap at /sitemap.xml -> The sitemap should be displayed in French. - Second, let the default language to be English. - Navigate to the French version of the website at /fr. - Access t
Original PR description
This PR introduces a regression test to ensure that the sitemap remains in the default language of the website, regardless of the language version being accessed. Tests 2 scenarios: - First,…
This PR introduces a regression test to ensure that the sitemap
remains in the default language of the website, regardless of the
language version being accessed.
Tests 2 scenarios:
- First, configure a website with English and French language.
- Set the default language to French.
- Access the sitemap at /sitemap.xml -> The sitemap should be displayed
in French.
- Second, let the default language to be English.
- Navigate to the French version of the website at /fr.
- Access the sitemap at /sitemap.xml -> The sitemap should now be
displayed in English.
This test addresses an issue that was previously fixed in commit
https://github.com/odoo/odoo/commit/809854c5d10735fb280141f5291bdb84d8d36569, but lacked a corresponding test to prevent future
regressions. This test ensures the bug reported in task-3935135 does ``
not reoccur.
**Added test in website_blog as it has routes that were translated.
Reference:
[1]: https://github.com/odoo/odoo/pull/154993#pullrequestreview-1900639267
Forward-Port-Of: odoo/odoo#190779--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr @moduon MT-9743 Forward-Port-Of: odoo/odoo#204487
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr @moduon MT-9743 Forward-Port-Of: odoo/odoo#204487