Tuesday, July 1, 2025
26 changes · saas-18.4
New functionality added to Odoo
VoIP users can now open a contact’s related CRM leads directly from the calling interface. This makes it easier for sales teams to connect phone conversations with lead follow-up without leaving the VoIP workflow.
Original PR description
This commit adds a button that connects the contacts to its leads via the VoIP module. It uses the same logic as "Applicant" button introduced before. Task-4855484 Community: https://github.com/odoo/odoo/pull/214031 Forward-Port-Of: odoo/enterprise#87294
Enhancements to existing features
Purchase routing rules can now use either standard receipt or dropship operation types. This makes it easier to configure dropshipping flows separately from regular warehouse receipts, reducing setup confusion for businesses using both processes.
Original PR description
*: stock_dropshipping With this commit ======================== Previously, only 'Receipt' operation types could be selected for rules with the 'Buy' action. However, with a dedicated 'Dropship' operation type, it's now possible to distinguish between standard receipts and dropship flows. This commit enhances the route rule configuration by allowing both 'Receipt' and 'Dropship' operation types to be selectable for 'Buy' actions. Now that 'Dropship' is an operation type, allowing it for 'Buy' rules ensures correct flow setup for dropshipping scenarios. task-4353843
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
The Time Off app now shows a helpful balance banner when viewing an employee's time off from their profile, making remaining leave easier to understand. It also corrects manager access when creating leave for subordinates and fixes balances by excluding expired allocations.
Original PR description
When coming from the time off smartbutton on the employee, having a small banner indicating the number of leaves remaining is useful. This PR adds this banner, the same as in the time off dashboard. The PR also fixes two bugs: - When an employee is a time off manager of another employee, he has access to the time off management menu. There, he can create new time offs for all subordinates employees. The field employee_id had the group hr_holiday_user, which is wrong as the time off managers don't necessarilly have this group. Removing the group allows the time off managers to select the correct employee, and the domain on the employee field ensures that the manager can only select subordinates employees. - In hr_leave kanban cards, the time off balance for that time off type is shown. The amount were incorrectly computed. This PR fixes the issue by filtering out the expired leave allocations. Forward-Port-Of: odoo/odoo#213792
This update refines several website builder controls so users can pick colors, switch builder tabs, and edit links more reliably. It also improves the visual consistency of color pickers and prevents template preview images from being cropped, making page customization smoother and clearer.
Original PR description
### [IMP] html_builder, website: improve color palette select UI This brings back the color palette on two columns and styles closer to what it looked like before [1]. [1]:…
### [IMP] html_builder, website: improve color palette select UI This brings back the color palette on two columns and styles closer to what it looked like before [1]. [1]: https://github.com/odoo/odoo/commit/9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-4879833 ### [FIX] html_builder: fix colors of theme tab colorpicker Commit [1] was supposed to fix the theme tab in colorpickers, but the variables were set on the wrong element. As the picker's popover is in another part of the DOM, the variables need to be set either on the `html` or the `body` element. [1]: https://github.com/odoo/odoo/commit/4a48b7ce1257 task-4367641 ### [FIX] html_builder: improve focus on builder tabs The `:focus-visible` state on the builder tabs (Add, Edit, Theme) clashed with the highlight styles as the outline did not have the same width and height. Additionally, `:focus-visible` and `:hover` states were incompatible. task-4879833 ### [FIX] html_builder: prioritize link popover over button overlays In the website builder, the button overlays may sometimes appear over the link popover. Adding a sequence makes sure that the buttons will appear first in the DOM order, and therefore under most other overlays. Steps to reproduce: - Drop enough snippets to have a scrollbar. - On the 1st snippet, have an inner column with a small width (just to make sure that the buttons will appear at the "right" place) and a button or a link at the bottom. - Click on the button => The overlay buttons appear over the link popover. task-4879833 ### [IMP] html_builder, web: integrate BuilderColorPicker styles Use dark styles for the BuilderColorPicker, like the rest of the builder interface. task-4879833 ### [FIX] website: do not crop template option We now insert actual images instead of svgs for the "Template" option on dynamic snippets. The alt is also fixed. task-4879833
When an online payment provider is activated, Odoo now automatically assigns the appropriate outstanding account to the related payment method. This reduces manual setup work and keeps payment accounting consistent with the Invoicing module, while excluding manual payment methods without external integrations.
Original PR description
In this PR: - When activating an Online Payment provider that creates a payment.method.line in a journal, automatically assign an Outstanding account to the payment method. - Uses the existing Outstanding Account resolution method from Invoicing module to ensure consistency across the system. - Applied to all Online Payment Providers that rely on provider integration, excluding manual payment providers without external integrations. task-4826385 Forward-Port-Of: odoo/odoo#216364 Forward-Port-Of: odoo/odoo#213554
Invoices can no longer be sent by email when the customer has no email address on file. This prevents invoices from being marked as sent incorrectly and prompts users to add the missing email first.
Original PR description
On send and print, When a partner has no email a popup prompts the user to add one but the `Send` button remains active. As a result, the email is sent to an invalid address, and the invoice is incorrectly marked as sent. We should block sending invoices by email if the partner has no email (same behavior as on Sales Orders). Task [link](https://www.odoo.com/odoo/project.task/4882552) task-4882552 Forward-Port-Of: odoo/odoo#215425
Discuss now keeps conversations visually stable while loading and uses smoother scrolling when jumping to the latest message or a specific message. This makes chat navigation feel more polished, especially on slower connections or in long conversations.
Original PR description
Before this commit, jump to present and to message in a discuss conversation was visually unappealing. This comes from: - jump to present scrolling is instantaneous, instead of smooth. - jump to…
Before this commit, jump to present and to message in a discuss conversation was visually unappealing. This comes from: - jump to present scrolling is instantaneous, instead of smooth. - jump to message scroll direction is always from top, when the frequent use-case is jump to older message thus should scroll to top. - message list is empty while the thread is loading, so the slower the connection the most visually unappealing it was. This commit improves scrolling experience with jump to present and jump to message as follow: - jump to present uses a smooth scroll effect similarly to jump to message - jump to message scroll direction is based on whether the message is older or newer to loaded set of messages. - message list stay visually in place while thread is loading. Task-4589532 Before  After 
Payroll runs can now generate payslips from a selected list of employees as well as from existing contract versions. This makes payroll processing more flexible when employee work entries are used and helps ensure the right contracts are selected automatically for the pay period.
Original PR description
Problem ---------- Generation of payslip with valid_versions is not enough flexible With work entries, we have to generate payslips for employees. Objective ---------- Change the _get_valid_versions_domain to _get_valid_versions to get only ids Adapt the signature of generate_payslips to use employees or versions to generate payslips Solution ---------- Now the _get_valid_versions give the valid versions ids, so we can directly browse them or add them in a domain, the domain is not forced The generate_payslips can work with versions (first argument by default) and employees, if employee_ids are given, this will fetch valid versions for these employee depending on the pay run config directly. So via the front, we can call generate_payslips with a list of employees if we don't have versions directly. (it will automatically select all contracts valid in the range of payrun as before with contracts) task-4900019
Users registering SEPA Direct Debit payments now see a banner listing any partners who do not have a valid SEPA mandate. This helps staff quickly identify which customer records need attention before payments can be processed.
Original PR description
When users try to register one or multiple payments with 'SEPA Direct Debit' method, and one or more partners don't have a valid SEPA mandate, a banner alerts the user and mention the names of the concerned partners. This makes it easier for the user because he directly sees the partners for which he has to set a SEPA mandate. task-4575537 runbot : https://runbot.odoo.com/runbot/bundle/18-0-sepa-missing-links-roto-353391 Forward-Port-Of: odoo/enterprise#81019
HR users can now open the employee contract version linked to a partially signed offer in a read-only view before countersigning. The signed contract button also consistently opens the correct version, including after a page refresh, reducing confusion during contract review.
Original PR description
New Versions tied to partially signed contracts are now read-only. A smartbutton for HR to view the employee version before countersigning. The smart button exists within the offer form view when the offer is partially-signed, it redirects to a read-only view of the employee version based on the partially signed contract. Fixes When the contract is countersigned, clicking on the "signed contract" smart button now leads to the correct version view. When the page is refreshed, the correct version is still loaded. Task-4873800
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