Tuesday, July 1, 2025
16 changes · saas-18.4
Resolved issues and error corrections
Employee creation now uses the employee's actual company from the start, preventing company-specific rules from being checked against the wrong organization. This reduces errors in multi-company setups, especially where HR rules depend on country-specific company settings.
Original PR description
=== Problem === Both hr_employee and hr_version have a stored field 'company_id'. The hr_version company_id field is a computed field that depends on the company_id field of the employee, if there is an employee (i.e. it is not a contract template). The problem is: when we create a new employee, the company_id field of the version will first be the current company, not the one of the created employee. This causes some problems, for example the constraints related to the company's country being wrongly executed on the hr_version. === Solution === To solve this problem, we explicitely set the correct company in the context when creating new employees, so that the version created by the ORM will have directly the correct country. These are batched by company to avoid loss in performance. task-4897733
Fixes an error that occurred when users uploaded a vendor bill PDF from the Requests for Quotation list. This restores the expected bill upload flow for purchase teams and prevents a blocking traceback during invoice creation.
Original PR description
In e7c93e5a6 we modified the call signature of `AccountMove._extend_with_attachments()` Now it takes not an `ir.attachment` recordset, but a list of dicts. But we forgot to modify the calling code in `PurchaseOrder.action_create_invoice`. As a result, the 'Upload Bill' button is currently broken. Steps to reproduce: - go to Purchase > Requests for Quotation - select a purchase order in the list view - click on `Upload Bill` and upload a PDF -> a traceback occurs.  This PR fixes the calling code in `action_create_invoice`. task-none
This fix restores a backup preview frame in the website builder so the previous page remains visible while a new page loads. It reduces distracting white flashes during navigation, making the editing experience feel smoother and more polished.
Original PR description
Since we refactored the website builder, the iframe fallback feature was lost: it is a second iframe that is useful to display the previous screen while we navigate from a page to another, so we reduce the white flash effect 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
Sales involving another company no longer fail when the user is limited to one allowed company. The fix ensures stock routing and delivery locations are handled correctly for intercompany transfers, preventing order confirmation errors and improving continuity for sales and warehouse teams.
Original PR description
**Steps to reproduce the issue:** - Install Stock, Sales applications - Set the allowed companies to Marc Demo to be only one company - Change the user to Marc Demo - Create a SO with partner another…
**Steps to reproduce the issue:** - Install Stock, Sales applications - Set the allowed companies to Marc Demo to be only one company - Change the user to Marc Demo - Create a SO with partner another company than Marc's company - Confirm the SO **Issue:** A traceback is raised: `No rule has been found to replenish "product" in "Virtual Locations/ Inter-company transit". Verify the routes configuration on the product.` **Root Cause:** - When the procurement group searches for a pull rule with a destination location set to the inter-company transit location (due to the partner's company being different), the rules for the inter-company transit location are not automatically applied. - The `_get_rule_domain` method https://github.com/odoo/odoo/blob/05cff3b7d866f6bc95c4b32f343ae14a4da946f2/addons/stock/models/stock_rule.py#L641-L653 modifies the destination location to the customer's location if: - The user belongs to the `base.group_multi_company` group. - The destination location is the inter-company transit location. - In this use case, the user does not belong to the `base.group_multi_company` group because they are restricted to a single allowed company. Additionally, the logic in `_compute_location_dest_id` https://github.com/odoo/odoo/blob/05cff3b7d866f6bc95c4b32f343ae14a4da946f2/addons/stock/models/stock_move.py#L227-L231 for inter-company transfers does not account for users with a single allowed company. **opw-4749870** 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#216317 Forward-Port-Of: odoo/odoo#211063
This fix prevents manually edited vehicle information from being overwritten during upgrades from earlier Odoo versions. It makes the fleet upgrade behavior safer and more reliable when new vehicle fields are introduced.
Original PR description
Description of the issue this PR addresses: When migrating from 18.2 to 18.3, certain vehicle fields (e.g., `category_id`) are unexpectedly reset. This issue is caused by the introduction of new field(s) in the vehicle model in 18.3 that share a common `_compute` function with existing fields. The shared `_compute` method updates all fields listed in `MODEL_FIELDS_TO_VEHICLE`, which unintentionally overwrites existing values, even those that have been manually edited, during the migration. While this could be mitigated by explicitly adding the new fields using `util.create_column(...)` in the upgrade script, a more robust and maintainable solution is to separate the compute logic for each field. This prevents unintentional side effects when new fields are added in the future and reduces dependency on strict upgrade scripts. Forward-Port-Of: odoo/odoo#215241
Portuguese accounting now shows the expected local account names for cash and demand deposits, making the chart of accounts clearer for Portuguese companies. The update also keeps point-of-sale setup working by finding the default cash account reliably regardless of the user's language.
Original PR description
**PROBLEM** The account Caixa (Cash) and Depósitos à Ordem (Demand deposits) are missing from the Portuguese localization. The accounts numerario and banco exist, but they don't have the right names. **STEPS TO REPRODUCE** - install the accountant and l10n_pt module. - select a Portuguese company and select the portuguese language. - in the Chart of Accounts, notice there is no account named Caixa and Depósitos à ordem. **FIX** We still need to translate "Bank" by Banco in some context. We override the "Bank" and "Cash" account in the pt journal template, using the account.account-pt.csv data. opw-4829413 related PR: https://github.com/odoo/odoo/pull/213522 Forward-Port-Of: odoo/odoo#216420 Forward-Port-Of: odoo/odoo#215369
Users working from a branch could hit an access error when opening Profit & Loss reports if a parent-company journal used a different currency. The fix lets Odoo safely read the needed currency information so authorized users can view accounting reports without requiring settings permissions.
Original PR description
### Steps to reproduce: - Create a branch to a company - Create a journal on the parent company with a different currency from the company - Create a user that can access both the parent company and the branch, but can't change the settings of Odoo - Log as this user, select only the branch as current company - Accounting > Reporting > Profit & Loss - Access Error ### Cause: `_compute_display_name` on the journal reads `journal.company_id.currency_id` without sudo. The current user cannot read on `company_id` because of the rule `res_company_rule_employee`. ### Solution: Use `sudo()` to read the currency of the company. opw-4847500 Forward-Port-Of: odoo/odoo#215455
Checkout no longer fails when a customer selects a warehouse pickup location that has no postal code. This prevents lost sales in countries or locations where postal codes are optional.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Enable `website_sale_collect`; 2. set up a warehouse in a country with optional zip codes; 3. configure warehouse as a pickup location; 4. add products…
Versions -------- - saas-18.3+ Steps ----- 1. Enable `website_sale_collect`; 2. set up a warehouse in a country with optional zip codes; 3. configure warehouse as a pickup location; 4. add products to its inventory; 5. via eCommerce, go to one of these products; 6. select warehouse as pickup location; 7. go to checkout; 8. attempt to pay for the order. Issue ----- Rendering error due to attempting to using `+` on strings & bools. Cause ----- Commit e3230547a53ce added a "Deliver to pickup point" line where it concatenates pickup location values into a single string like https://github.com/odoo/odoo/blob/8103619c51525bcdaa754c39c7d27560b3f6861e/addons/website_sale/views/templates.xml#L2686 The intention is that if the key doesn't exist, the empty string should be used. Issue is that when no zip code is provide, using `get` will return the boolean `False` instead of falling back on the empty string, leading to the rendering error. Solution -------- When sending the pickup location data to the front-end, provide empty strings instead of boolean values. opw-4893036 Forward-Port-Of: odoo/odoo#216112
Salary offer forms now keep the correct signature template information when contract versions are loaded, preventing an error during submission. Applicant stage display behavior was also adjusted so hiring status steps remain visible more consistently.
Original PR description
By assigning the contract_template_id to version.contract_template_id when it's loaded and assigned to hr.employee.contract_template_id This prevents the error: "No signature template defined on this version.." when trying to submit the salary configurator form. task-4873800
Time off approvers assigned on an employee record can now approve or refuse leave requests dated in the past. This fixes a workflow issue so managers can correctly process older or backdated time off records without extra intervention.
Original PR description
With this commit, a time off approver (define in employee form) can approve/refuse a past leave. task-4868496 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#215405
Sales Planning now installs correctly even if the standard Hours unit of measure was previously deleted. The system recreates the needed unit when required and prevents it from being removed in this context, reducing setup failures for customers using planning and sales features.
Original PR description
Steps to reproduce: --- - Install `sale_management` module - Enable `Units of Measure & Packagings` - Delete `Hours` in Units & Packagings - Install `sale_planning` module Traceback: --- ```…
Steps to reproduce:
---
- Install `sale_management` module
- Enable `Units of Measure & Packagings`
- Delete `Hours` in Units & Packagings
- Install `sale_planning` module
Traceback:
---
```
ValueError: External ID not found in the system: uom.product_uom_hour
ParseError: while parsing /home/odoo/src/enterprise/saas-18.2/sale_planning/views/planning_role_views.xml:26, somewhere inside <record id="planning_role_view_tree_inherit_sale_planning" model="ir.ui.view">
<field name="name">planning.role.list.inherit.sale.planning</field>
<field name="model">planning.role</field>
<field name="inherit_id" ref="planning.planning_role_view_tree"/>
<field name="arch" type="xml">
<field name="resource_ids" position="after">
<field name="product_ids" widget="many2many_tags" placeholder="e.g. Cleaning Services" domain="[('planning_role_id', '=', False), ('type', '=', 'service'), ('sale_ok', '=', True)]" context="{ 'default_type': 'service', 'default_planning_enabled': True, 'default_planning_role_id': id, 'default_uom_id': %(uom.product_uom_hour)d, }"/>
</field>
</field>
</record>
```
The error occurred at [1] because the user deleted `Hours` from `Units & Packagings` before attempting to install the other module.
This commit resolves the issue by calling the `ensure_uom_hours` method before updating the `Hours` unit of measure in the data file. This method ensures the UoM is recreated if it no longer exists in the database.
[1]- https://github.com/odoo/enterprise/blob/adfa1ff2ee56b8d43666cd7c2565d6e9430aae48/sale_planning/views/planning_role_views.xml#L38
sentry-6595283261
Forward-Port-Of: odoo/enterprise#89046
Forward-Port-Of: odoo/enterprise#85286Fixed an issue where discounts on regular sales order lines could be unexpectedly removed when a subscription order was saved or closed. This helps ensure quoted and invoiced discounts remain accurate for customers using subscriptions alongside one-time products.
Original PR description
**Issue 1** - Have a pricelist with the "Discount policy" == "without_discount" - Using this pricelist, create a SO with 1 subscription line and 1 non-subscription line - Set a discount on both lines…
**Issue 1** - Have a pricelist with the "Discount policy" == "without_discount" - Using this pricelist, create a SO with 1 subscription line and 1 non-subscription line - Set a discount on both lines - Save the SO - Issue: the discount on the non-subscription line has been reset to 0.0 **Issue 2** - Using the previous SO, add back a discount value for the non-subscription line - Confirm the SO and invoice it - Close the subscription - Issue: the discount on the non-subscription line has been reset to 0.0 **Cause** Both issues come from the fact that `order_id.subscription_state` is a dependency of `_compute_discount` in `sale_subscription`. The super is called for non-subscription lines, recomputing the discount. **Solution** It is not possible to know which dependency triggered the compute, therefore the solutions are to: - avoid a recompute at creation after the `web_save` by not writing on the `subscription_state` field if not necessary - avoid calling super for lines if the subscription is closed opw-4645579 Forward-Port-Of: odoo/enterprise#88816 Forward-Port-Of: odoo/enterprise#84754
Chile POS users now see the actual outstanding invoice amount when settling customer invoices, instead of an incorrect default of $1. This prevents undercharging mistakes and helps cashiers complete settlements accurately.
Original PR description
**Problem:** When trying to settle an order in POS with a Chilean company, the amount to be settle will be 1$, regardless of how much needed to be settled. **Steps to reproduce:** - Set the company to a Chilean company. - Make an invoice for a Chilean customer and confirm it. - Go to pos, and click settle invoices for your client, chose the invoice you just made. - The amount will be 1$ **Why the fix:** The field *pos_amount_unsettled* was not loaded into the invoice if the company is from Chile. It resulted in it being undefined, thus it was set to 1 afterwards. We now load this variable into the invoice when loading the data. opw-4856764 Forward-Port-Of: odoo/enterprise#87881
Employees can now open and sign custom salary contract offers generated from contract templates. The fix ensures the signing link uses the correct signer-specific access information, preventing blocked or broken signing flows.
Original PR description
Steps to Reproduce: - Create a new contract template. - Define signatories to it(pref: employee) - create a offer linked to an applicant and try generating a offer and signing Fix: - Since the sign creating new role every time when we add new signer, we can't use the existing employee role id anymore. - Hence we will get the access token from signatory linked with the signer in the contract template and use that. task-4894597 Forward-Port-Of: odoo/enterprise#87420
Spreadsheet dashboards now treat creation date filters as date-and-time values, so results better reflect each user's timezone. This prevents dashboards such as CRM leads and HR referrals from including or excluding records around day boundaries incorrectly.
Original PR description
The generated domain is wrong when filtering on the date. It doesn't account for the user timezone because the field matching is given as a "date" field instead of being a "datetime".
The generated domain looks like `[("create_date", ">=", "2025-06-27")]` instead of `[("create_date", ">=", "2025-06-27 21:59:59")]`
I'm fixing this in 18.0 because this fix won't affect existing databases (without updating the modules). The fix would be useless and I don't want to go though the pain of forward-ports for nothing. New databases are created in 18.0 every day (latest LTS)
Task: 4903362
Forward-Port-Of: odoo/enterprise#88807
Forward-Port-Of: odoo/enterprise#88730This fixes an access error that could prevent certain branch users from opening Profit and Loss reports when journals belonged to a parent company with a different currency. The report can now display the needed journal information without requiring those users to have broader company settings permissions.
Original PR description
This commit is the counterpart of a commit in community to add a test. ### Steps to reproduce: - Create a branch to a company - Create a journal on the parent company with a different currency from the company - Create a user that can access both the parent company and the branch, but can't change the settings of Odoo - Log as this user, select only the branch as current company - Accounting > Reporting > Profit & Loss - Access Error ### Cause: `_compute_display_name` on the journal reads `journal.company_id.currency_id` without sudo. The current user cannot read on `company_id` because of the rule `res_company_rule_employee`. ### Solution: Use `sudo()` to read the currency of the company. opw-4847500 Linked PR: https://github.com/odoo/odoo/pull/215455 Forward-Port-Of: odoo/enterprise#88848 Forward-Port-Of: odoo/enterprise#88339