Monday, July 7, 2025
10 changes · saas-18.1
Resolved issues and error corrections
This fixes an internal testing issue where stock quantity report tests could fail around midnight because different parts of the test used different dates. The change makes the tests use a fixed time, improving reliability without changing user-facing stock features.
Original PR description
The tests: - `test_report_stock_quantity` - `test_report_stock_quantity_with_product_qty_filter` can fail if the test class was instantiate at midnight and the tests launched at 00:01. The issue has…
The tests: - `test_report_stock_quantity` - `test_report_stock_quantity_with_product_qty_filter` can fail if the test class was instantiate at midnight and the tests launched at 00:01. The issue has been explained extensively in d1e11dc2b41e66709ddd89beded32872af4118b9 Here is a modest retranscription of its holy analysis: The Test class `TestReportStockQuantity` inherit from `TransactionCase`. So, once initialized, a SQL transaction is started and is the same for all the tests of the class: https://github.com/odoo/odoo/blob/d86409d93e096126b32cbb35f442db332628375d/odoo/tests/common.py#L775-L778 Also, in a SQL request, the method `now()` does not really return the current date: > Notice that NOW() and its related functions return the start time of the current transaction. In other words, the return values of the function calls are the same within a transaction. (https://www.postgresqltutorial.com/postgresql-date-functions/postgresql-now/) So, if we we start all the tests of the class `TestReportStockQuantity` at the end of D01. The SQL transaction is created and the tests are executed one by one with a NOW() corresponding to D01. However, certain indiviual tests might be launched on the following day D02 because it takes time to run the rest of the tests of the class: In particular, the python "today()" will notgive the same date as the SQL NOW and the queries of the test will simply not perform the expected. E.g: https://github.com/odoo/odoo/blob/d86409d93e096126b32cbb35f442db332628375d/addons/stock/tests/test_report_stock_quantity.py#L105-L110 runbot-226726 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#215687 Forward-Port-Of: odoo/odoo#215424
Archiving an employee now preserves the correct departure information even when that employee is responsible for another person's time off. This prevents missing or incorrect records during the employee departure process, improving HR data accuracy.
Original PR description
When we archive an employee that is the time off responsible of another employee, the `_clean_leave_responsible_users` method will clear our cache before we set some departure related fields. This will cause us to have to recompute the relation for `employee_ids` and the domain that ensures the suggested employees in the wizard are not already archived will prevent us from finding the employee we were archiving. To ensure these fields are written properly, we save the value of `employee_ids` before archiving the employee. opw-4729600
Timesheets now correctly preserve custom planning fields added through Studio when a user saves a new entry. This prevents entered information from being overwritten by automatic account distribution defaults, reducing data loss and rework.
Original PR description
### Steps to reproduce: - Navigate to a Project > View (Timesheets) - Open studio and add x_plan2_id for example to the view - Try creating a new timesheet and set a value for the field we added using studio - Save and notice the field doesn't keep its value ### Cause: This is mainly happening because when getting the plan_ids for the account we are gonna fill we just get the account in the distribution and ignore if the user is setting another value ### Fix: We check the create vals_list if a plan has value we set it before setting the account in the distribution opw-4716041 Forward-Port-Of: odoo/odoo#214865
This fix adjusts automated shop floor test checks so they are not affected by unrelated demo data. It helps keep build validation stable and reduces false failures during development and release preparation.
Original PR description
### Issue: Certain shopfloor tests make assert on the number of records present in the shopfloor: - test_shop_floor_my_wo_filter_with_pin_user - test_automatic_backorder_no_redirect These assert can not be reliable due to demo-data's adding unrelated records e.g. https://github.com/odoo/enterprise/blob/5bfadae317ee47ac34703d4cc222677ac677cc7d/purchase_mrp_workorder_quality/data/purchase_mrp_workorder_quality_demo.xml#L79-L84 runbot-build-error-226734 Forward-Port-Of: odoo/enterprise#88412 Forward-Port-Of: odoo/enterprise#88005
Customer statements now use the sender and reply-to addresses configured on the Customer Statements email template. This ensures customer communications come from the intended business address instead of defaulting to the current user's email.
Original PR description
Steps to reproduce:
Go to Settings> Email templates
Open the template Customer statements
Change the value in email from or reply to
Go to Accounting > Customers > Customers
Open a customer
Send a customer statement
Issue:
The address in use is not the same as we specified in the customer template
Cause:
if no email_from is provided, we will use the current partner's use's email address https://github.com/odoo/odoo/blob/cc0aaff5f93d5332c60d5bd8097173326a0a12b3/addons/mail/models/mail_thread.py#L2863-L2864
We don't check if the template has any email_from address defined
Note:
As from this fix, if no address is defined, by default it will be the `{{ object._get_followup_responsible().email_formatted }}`
opw-4864155
Forward-Port-Of: odoo/enterprise#88262Users can now open Studio from the Documents app even after creating a shortcut to a file. This prevents an error that interrupted customization work in Documents and keeps the workflow smooth.
Original PR description
Steps: - Install `documents` and `studio` - Open documents, go to list view - Select a random file and 'Create a shortcut' via the actions - Try to open studio - traceback opw-4900667 Forward-Port-Of: odoo/enterprise#89508
Installing Field Service Sales no longer fails if the default Services product category was previously deleted. This prevents a setup-blocking error and lets businesses install the module even when product categories have been customized.
Original PR description
Currently a ParseError is arising when the user installs the `industry_fsm_sale` module after deleting the `Services` in Product Categories/Configuration. Steps to reproduce: --- - Install…
Currently a ParseError is arising when the user installs the `industry_fsm_sale` module after deleting the `Services` in Product Categories/Configuration.
Steps to reproduce:
---
- Install `Invoicing` application (without demo data).
- Invoicing > Configuration > Product Categories > Delete `Services`
- Now install `industry_fsm_sale` module
Traceback:
---
```py
ValueError: External ID not found in the system: product.product_category_services
ParseError
while parsing /home/odoo/src/enterprise/saas-18.3/industry_fsm_sale/data/industry_fsm_data.xml:5, somewhere inside <record id="field_service_product" model="product.product">
<field name="name">Field Service</field>
<field name="project_id" search="[('id', '=?', ref('industry_fsm.fsm_project', raise_if_not_found=False)), ('is_fsm', '=', True)]"/>
<field name="service_tracking">task_global_project</field>
<field name="type">service</field>
<field name="categ_id" ref="product.product_category_services"/>
```
The error occurs because the user deleted `Services` in Product Categories, and then tried to install the other module.
This commit resolves the error by providing a False value for the field if the product category is missing.
sentry-6377659355Miscellaneous changes
Scenario: - insert the last blog posts widget in a page - open editor and edit (eg. Filter Intensity) the cover of a post - save Result: the change is lost Cause: the content of the widget is dynamic, and we delete the content in cleanForSave (that call the destroy of the widget) before saving, so the change are not saved. Fix: make the dynamically added cover widget unselectable, the cover of the blog post can still be changed in other locations (blog post list, blog post page).
Original PR description
Scenario: - insert the last blog posts widget in a page - open editor and edit (eg. Filter Intensity) the cover of a post - save Result: the change is lost Cause: the content of the widget is dynamic, and we delete the content in cleanForSave (that call the destroy of the widget) before saving, so the change are not saved. Fix: make the dynamically added cover widget unselectable, the cover of the blog post can still be changed in other locations (blog post list, blog post page). opw-4633287 __PR NOTE:__ in verson before 18.0, the cover was not selectable probably from the .o_not_editable on `.s_dynamic_snippet_content` ancestor element. I've not found what changed (there was some change to dynamic snippet and widget blog post) that make it selectable now. Forward-Port-Of: odoo/odoo#214651 Forward-Port-Of: odoo/odoo#210079
During odoo/enterprise#60393 some po files that had been deleted in odoo/odoo#172429 and odoo/odoo#172269 were re-added in. We remove them now as they are out of date + are not reachable to be translated/fixed without a PR. Forward-Port-Of: odoo/enterprise#89301
Original PR description
During odoo/enterprise#60393 some po files that had been deleted in odoo/odoo#172429 and odoo/odoo#172269 were re-added in. We remove them now as they are out of date + are not reachable to be translated/fixed without a PR. Forward-Port-Of: odoo/enterprise#89301
Currently when /iot/setup method is called if the iot box record exists we always update the record with the received data, even if the data is the same as the record's data. This PR only updates it if the data changes Forward-Port-Of: odoo/enterprise#88043
Original PR description
Currently when /iot/setup method is called if the iot box record exists we always update the record with the received data, even if the data is the same as the record's data. This PR only updates it if the data changes Forward-Port-Of: odoo/enterprise#88043