Daily updates from Odoo
Tuesday, July 1, 2025
50 changes
16 changes
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
5 changes
Resolved issues and error corrections
CSV bank statement imports now avoid failing when automatic matching encounters conflicts, helping users complete imports more reliably. Matching is also moved to a background process, which should make imports faster and prevent one reconciliation issue from rolling back the whole import.
Original PR description
When doing an import of a csv in the bank rec widget, it could happens that the try_auto_reconcile throw an error which will lead in the rollback of the import. By triggering the schedule action auto_reconcile_bank_statement_line we will do the try_auto_reconcile in the back ground which will speed up the import process When importing, we pass a batch of statement lines to the try_auto_reconcile function, which identifies possible reconciliation candidates for each line. The issue arises because we iterate through each statement line and assign its potential candidate without checking for conflicts: if two statement lines map to the same candidate, we don’t verify whether that candidate has already been reconciled with a different line. opw-4888045,4890008
Fixed an issue where discounts on regular sales lines could be cleared when saving, invoicing, or closing a sales order that also contains subscription lines. This helps preserve agreed customer discounts and avoids manual corrections for mixed subscription and non-subscription orders.
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
Fixed an issue where job offer contracts based on custom signing templates could fail to open for signing. The process now uses the correct signer access details from the template, helping HR teams complete offer signing without interruption.
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
This fix updates the Mexican payroll rules so subsidy eligibility is evaluated with the right conditions. It helps ensure payroll calculations apply subsidies only when appropriate, reducing incorrect payslip results.
Original PR description
task-4690544 Forward-Port-Of: odoo/enterprise#84780
Helpdesk tickets will no longer be closed when automated email scanners check links in notification emails. Only a real customer visit to the close-ticket link will trigger closure, reducing accidental ticket closures and support disruption.
Original PR description
Currently some customers with email scanners will have their ticket closed soon after it's opened. Steps to reproduce ----- 1. Enable "Closure by Customers" on the helpdesk team 2. Create a new ticket 3. Send a HEAD request to the "Close ticket" link in the received email, using `curl -I <url>` 4. The ticket gets closed Cause ----- Some email scanners send HEAD requests to links contained in emails, which is incorrectly interpreted as a user action. Fix ----- Implement a check so that only GET requests to the route will close the ticket. opw-4837167 Forward-Port-Of: odoo/enterprise#88547
10 changes
Resolved issues and error corrections
Users who work across a parent company and its branch can now open the Profit and Loss report without hitting an access error. The fix ensures journal currency information is read safely when the user has limited 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
Fixed an issue where child companies with their own VAT number did not receive the expected VAT return records. This ensures businesses using company branches can access and manage the correct tax returns for each eligible child company.
Original PR description
Steps to reproduce: - Create a company (for example a Belgian one) and set the vat - Create a child company with same country, but different vat - set the account opening date for both companies - open the tax returns page with the child company -> the child company should have VAT returns associated, because it's the main company for the vat branch, but it doesn't contain anything Forward-Port-Of: odoo/enterprise#88868 Forward-Port-Of: odoo/enterprise#88061
This fixes an issue where discounts on regular sales order lines could be unintentionally reset when subscriptions were saved, invoiced, or closed. Businesses using subscriptions alongside one-time sale items can now keep manually entered discounts intact, reducing billing errors and manual corrections.
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
This fix ensures overtime is paid on top of an employee's regular fixed wage instead of reducing the calculated hourly rate. It also prevents casual loading from being incorrectly applied to overtime, improving payroll accuracy for Australian employees.
Original PR description
Bug: 1. Worked overtime hours are included within the gross paid amount of a contract rather than being added on top. 2. Casual loading rate applies to Overtime hours. Steps to reproduce: 1. Create a…
Bug: 1. Worked overtime hours are included within the gross paid amount of a contract rather than being added on top. 2. Casual loading rate applies to Overtime hours. Steps to reproduce: 1. Create a payslip for an employee with a contract of Fixed wage of 2000 per week. 2. The created payslip is of correct amount with the standard 40-hours work week. 3. Add a work entry of type Overtime with duration of 4 hours. Recompute the worked days amounts. Current behavior: The total remains 2000 and the computed hourly rate becomes 2000/44=45.45 Expected behavior: The hourly rate should remain the same 50. The total should increase to be: fixed_wage + hourly_rate * overtime hours 2000 + 50 * 4 = 2200 Fix: 1. While computing the amounts for each worked days type, exclude hours of type Overtime from total hours when calculating the hourly rate. 2.The casual loading rate should not apply to Overtime work entry types. task-4617681 Forward-Port-Of: odoo/enterprise#88100 Forward-Port-Of: odoo/enterprise#83171
Fixes an issue where enabling form access in Website Studio was not applied when saving a form. The change also makes form access edits part of the change history and clarifies the option with a tooltip, reducing confusion for website editors.
Original PR description
When [1] converted the form access option to fit inside `html_builder`, the form access was supposed to be enabled upon saving a form, but the used selector was incorrect, which led to the form access not being enabled. Also, a `ModelCache` was created which kept track of the same model but according to various ways to write this key. This system was flawed and led to reaching distinct object depending on the used "synonym" key. This commit: - fixes the selector used during the save operation - removes `ModelCache` and uses a plain cache with the model name as key in all situations - makes changes to form access included in the history - adds a tooltip on that confusing option [1]: https://github.com/odoo/enterprise/commit/689a2186fbe3b932b90bef3b64716c8443bad551 task-4367641 Forward-Port-Of: odoo/enterprise#88271
This fixes an issue where Chilean POS invoice settlement always showed $1 instead of the actual outstanding amount. The correct unsettled invoice amount is now loaded, helping cashiers collect the right payment and avoid manual corrections.
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
Portal users using a shared project folder link can now upload documents without running into an access error. This keeps external collaboration working as intended when project folders are shared with upload permissions.
Original PR description
To reproduce: ============= - install documents_project - create project - go to documents and get share link of the project's folder with permission to upload (anyone with the link can upload) - open the share link in a new browser window and connect as portal user - upload a document -> access error Problem: ======== while uploading a document, we will need to read `partner_id` from the linked project, but the portal user does not have access to the project Solution: ======== read as `sudo` opw-4782062 Forward-Port-Of: odoo/enterprise#88427 Forward-Port-Of: odoo/enterprise#87301
Accounting PDF reports in right-to-left languages now fit properly on the page when many columns are included. This prevents printed reports such as Aged Payable from being cut off, improving readability for users working in RTL languages.
Original PR description
Steps to reproduce: - Set language to RTL Orientation - Go to Accounting > Reporting > Aged Payable - Add multiple columns to report - Print as PDF Issue: When enough columns have been added to the report, the report will overflow the right side of the page Cause: Wkhtmltopdf does not correctly shrink the table if the direction is specified on the body of the document opw-4746361 Forward-Port-Of: odoo/enterprise#88770 Forward-Port-Of: odoo/enterprise#87520
Kenyan eTIMS invoice submissions that time out are now checked before being retried. If the invoice was already accepted, Odoo retrieves the official details such as the QR code instead of sending it again, reducing the risk of duplicate government invoices.
Original PR description
When a timeout occurs during invoice submission to eTIMS, we had no way to know if the invoice was actually received. Retrying could lead to duplicate invoices being accepted by the government. With the release of the selectInvoiceDetails endpoint, we now check if the invoice was already submitted before retrying. If found, we treat it as successfully sent and retrieve its details (QR code, etc). If not, we proceed to resend. task-4863787 Forward-Port-Of: odoo/enterprise#88858 Forward-Port-Of: odoo/enterprise#88608
Spreadsheet dashboards now apply date filters using the correct time-aware field type, so results better match each user's timezone. This prevents records from being incorrectly included or excluded around date boundaries in newly updated dashboard data.
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#8873019 changes
Resolved issues and error corrections
Malaysia e-invoicing now allows credit notes to be reported even when the original invoice was not previously sent to MyInvois, supporting cases where older invoices predate MyInvois use. The issue date sent to MyInvois is also corrected to use the current UTC date, matching platform requirements.
Original PR description
So far, we have enforced that credit notes must be linked to an invoice that has been sent to MyInvois. In real life, this is too strict. Users could be issuing credit notes for invoices created before MyInvois was used, in which case these must still be reported to MyInvois even though the original invoice isn't on the platform. This also fixes a small issue with the issue date, which was set to the invoice date up until now but on their platform they explicitly ask for today in UTC timezone. task-4889022 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#215347
Argentina B invoices for final consumers or exempt customers will now include the required tax breakdown table even when VAT totals are 0.0. This keeps printed PDFs aligned with ARCA expectations and avoids missing compliance information for zero-tax sales.
Original PR description
### **Description of the issue/feature this PR addresses:** When doing an Invoice B to exempts customer we have a problem the RG Legend new table is not showing: this because if the VAT Content or…
### **Description of the issue/feature this PR addresses:** When doing an Invoice B to exempts customer we have a problem the RG Legend new table is not showing: this because if the VAT Content or other taxes sum is 0.0 (we are not showing any information if sums 0.0) After checking with ARCA Online PDF sxampels, and some feedback of Argentinen users, we found out that the Legend should be always present. event if the totals of theTax Breakdown are shown with 0.0 ### **Steps to reproduce** Go to an Argentina Company Create a new invoice for "Final Consumer" with document type "Invoice B" Create a product line with tax 0 (could use either VAT Exempt, VAT 0, VAT Not Taxed) Print the PDF ### **Current behavior before PR:** The PDF is NOT showing the Tax Breakdown table  ### **Desired behavior after PR is merged:** The PDF is showing the Tax Breakdown with the line VAT Content 0.0  --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Manual Forward-Port-Of: https://github.com/odoo/odoo/pull/207367
This fix keeps the source reference on stock transfers when items from different replenishment actions are combined. Instead of clearing the origin field, Odoo now appends the additional reference so users retain traceability for inventory movements.
Original PR description
**Current behavior:** During the assignment of a picking, if any of its moves have an origin that does not match its own, the origin will be cleared altogether. **Expected behavior:** The different…
**Current behavior:** During the assignment of a picking, if any of its moves have an origin that does not match its own, the origin will be cleared altogether. **Expected behavior:** The different origin should be appended to the existing origin string (as is done in batch replenishment, for example). **Steps to reproduce:** 1. Create 2 products, create a secondary warehouse 2. Create an orderpoint for each product, make the route on both of them the (first?) pointed to by `resupply_route_ids` on the primary warehouse 3. Set `qty_to_order` 1 on each of the orderpoints, and one at a time click the 'Order' button 4. The move generated for each replenishment action will ultimately be added to a single picking -> in the end see that its `origin` field is cleared **Cause of the issue:** We currently decide to clear the picking origin during assignment if any of its moves have a different origin. **Fix:** Instead, append the different origin string to the picking. opw-4749519
Fixes an issue where images in email templates could stay locked to a previously saved size after being edited. Users can now resize images or return them to their default size without old dimensions overriding their changes.
Original PR description
Problem: When resized images (e.g., with `style.width: 50%`) are processed by `convert_inline`, `width` and `height` attributes may be added for email client compatibility. These attributes override resizing changes, forcing the last saved dimensions and preventing fallback to the image's default size. Solution: Remove `width` and `height` attributes from the content inserted into the editor. They will be correctly re-applied on save if needed. Steps to reproduce: - Create a new email template - Add an image - Resize the image to 100% - Save - Resize the image back to default - The image keeps the 100% size opw-4863515 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix stops refunds in Point of Sale from being paid again with an online payment method, a flow that is not supported. It prevents affected POS sessions from getting stuck and failing to close after such a refund.
Original PR description
**Problem:** When refunding an order that has been done in the frontend from the backend, then when trying to pay for it again using an online payment method, it will currently work. The problem is…
**Problem:** When refunding an order that has been done in the frontend from the backend, then when trying to pay for it again using an online payment method, it will currently work. The problem is that doing this will prevent the user from closing their session afterwards. The issue is that refunding through online payment method is not supported but is going though either way. **Steps to reproduce:** - Have an online payment method. - Go to your POS session and make a purchase, pay for it in cash. - Go back to the backend, to orders and chose your order. - Return the products and click payment to pay for it again. - Chose your online payment method and make the payment. - Try to close your POS session, an error prevents you from doing so. **Why the fix:** The problem is that an error should be thrown when trying to pay the refund with an online payment method. But this error is never reached. It was reached before this commit https://github.com/odoo-dev/odoo/commit/2dce0f22e92299b17162343e3629dcdab8a697b5 This commit is fixing an error that has since been avoided by this commit https://github.com/odoo-dev/odoo/commit/0c8f0d730465028657ff8da28e7ab14e2df08f69 The use case does not even go through the fixed *create* function anymore, so there should be no problem reverting the fix. Before said commit, we set the *online_account_payment_id* whether it exists or not. This then allows us to check if one of them is None later on. If it is, it means we can't create the online payment, as we can't create one without an accounting payment. After said commit, we didn't add it if the accounting payment didn't exist, so the error was never thrown as the code couldn't be reached. opw-4815049
When an invoice with deferred revenue or expenses is reset to draft under Audit Trail, posted deferred entries are now cancelled as intended instead of being reversed. This keeps accounting records consistent with audit protections and avoids incorrect reversal handling for affected invoices.
Original PR description
**Steps to reproduce:** - Install accountant - In Accounting settings, activate "Audit Trail" - Create an invoice: * Customer: [any] * Invoice Lines: - Product: [any] - Start Date: [2 months ago] -…
**Steps to reproduce:**
- Install accountant
- In Accounting settings, activate "Audit Trail"
- Create an invoice:
* Customer: [any]
* Invoice Lines:
- Product: [any]
- Start Date: [2 months ago]
- End Date: [2 months later]
- Confirm the invoice
=> Deferred Entries are created. Posted for the previous months and in draft for the future ones.
- Reset the invoice to draft
**Issue:**
The draft entires are correctly unlinked, but the posted ones are reversed instead of being cancelled.
**Cause:**
This fix https://github.com/odoo/odoo/commit/cc448bf77aa3d11e634e6bab6da1690a1b67a723 is supposed to cancel the deferred entries when the move is protected by the audi trail.
However we never get into the `elif move._is_protected_by_audit_trail():` branch because its condition is also included in the previous `if not move._can_be_unlinked():` branch.
Linked enterprise PR (test): https://github.com/odoo/enterprise/pull/88992
opw-4891975
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prPoint of Sale self-invoicing now updates an existing customer record when the customer enters new details through the receipt QR code form. This prevents outdated customer information, such as VAT numbers, from remaining in the back office after a self-invoice is created.
Original PR description
When doing a self invoice with the QR code on the PoS receipt, if a partner was linked to the order, the record would not be updated with the values entered in the self invoice form. Steps to reproduce: ------------------- * Enable the self service invoice feature in the PoS settings. * Open a PoS session. * Make and order with a partner set on it. * Finalize the order and scan the QRCode on the receipt. * Fill the form with some new informations (like a new VAT number) > Observation: Check the partner on the backend, the values are not updated. Why the fix: ------------ We update all the mandatory and optionnal fields of the partner record with the values entered in the self invoice form. opw-4676244
This fix prevents Odoo from creating an incorrect extra delivery transfer when a confirmed sales order quantity is reduced on routes using a destination location from the rule. Inventory adjustments now use the intended destination location, keeping delivery records and stock movements accurate.
Original PR description
Steps to reproduce: - Install Sales and Stock - Activate the multi-step routes setting - Go to a Delivery route in the warehouse - Change the `location_dest_id` of the operation type set on the rule…
Steps to reproduce: - Install Sales and Stock - Activate the multi-step routes setting - Go to a Delivery route in the warehouse - Change the `location_dest_id` of the operation type set on the rule - Enable the "Location Dest. Taken from Rule" checkbox - Ensure `rule.location_dest_id` and `operation_type.location_dest_id` are different - Create a Sales Order (SO) for a product with quantity = 5 and confirm - Change the SO line quantity to 3 and save Issue: A second picking is created with a move taking the product from `rule.operation_type.location_dest_id -> rule.operation_type. location_src_id` with quantity = -2. This happens because the decrease in the SO quantity triggers a negative move, and this move is not merged with the existing positive move. Instead, a new move is created in the opposite direction. In `_merge_moves`: https://github.com/odoo/odoo/blob/3c4275fb00255e519f01bf5547eff1db3a59d4b5/addons/stock/models/stock_move.py#L1191-L1193 It checks if the negative move has similar characteristics to the existing positive moves. However, the `neg_key(neg_move)` differs in `location_dest_id`, so the merge fails. This happens because the negative move does **not** read the `location_dest_id` from the rule — unlike the procurement, which **does** use the rule and therefore creates positive moves with the correct destination. When the negative move is created with the procurement, it initially has the correct `location_dest_id`. But then: https://github.com/odoo/odoo/blob/b984c72df398c4fe942d8894442e4e893ca0660e/addons/stock/models/stock_move.py#L1191 triggers `_compute_location_dest_id`, which doesn't consider the `rule.location_dest_id` and defaults to `operation_type. location_dest_id`, causing the merge to fail due to mismatched destination_locations. The positive move has read the correct value, because when it was assigned to a picking, the picking has the correct destination from the procurement. But for the neg_move it has picking None so it maps to the operation_type without consdiering the location from rule checkbox. opw-4793171
This fixes crashes that could happen when forms accidentally included technical binary fields containing unexpected data. Odoo now avoids showing unsuitable technical binary fields in generated forms and handles unusual binary values more safely, improving reliability for users.
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#216377 Forward-Port-Of: odoo/odoo#213967
Fixed a rounding problem when breaking down multi-level Bills of Materials for kit deliveries. This prevents incorrect component quantities from being reserved or delivered, helping inventory and fulfillment stay accurate.
Original PR description
## How to reproduce - Create 3 products: "FNS" / "CMP 1" / "CMP 2", the three of them with an UoM of 2 digits precision - Create Kit BoM for 1 Unit of "FNS" using 10 Units of "CMP 1" - Create Kit BoM…
## How to reproduce
- Create 3 products: "FNS" / "CMP 1" / "CMP 2", the three of them with an UoM of 2 digits precision
- Create Kit BoM for 1 Unit of "FNS" using 10 Units of "CMP 1"
- Create Kit BoM for 5000 Units of "CMP 1" using 50 of "CMP 2"
- Check "FNS" BoM Overview:
- "CMP 2" quantity shows the correct 0.10 Units (1 * 10 / 5000 * 50) (ok)
- Create Delivery order for 1 Unit of FNS
- "CMP 2" quantity is 0.50 Units (KO)
OPW-4804958
---
### BoM Overview

### BoM exploded

---
### Test result without fix:
```
2025-06-25 00:00:00,000 28629 ERROR oes_test_17 odoo.addons.mrp.tests.test_bom: FAIL: TestBoM.test_02_explode_rounding
Traceback (most recent call last):
File "/home/odoo/projects/odoo-src/multiverse/src/17.0/odoo/addons/mrp/tests/test_bom.py", line 63, in test_02_explode_rounding
self.assertEqual(lines[0][1]['qty'], 0.10)
AssertionError: 0.5 != 0.1
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#215821Customer follow-up reports now ignore accounting entries that do not have a due date or payment terms when deciding whether action is needed. This prevents customers from being flagged incorrectly and avoids misleading statements showing an outstanding balance of zero.
Original PR description
Linked to a commit in enterprise for account_followup: https://github.com/odoo/enterprise/pull/88515 ### Issue: It is possible to break the followup reports by directly creating entries in the past.…
Linked to a commit in enterprise for account_followup: https://github.com/odoo/enterprise/pull/88515 ### Issue: It is possible to break the followup reports by directly creating entries in the past. ### Steps to reproduce: - Example on Belgian loca - Accounting Dashboard > Misc > new Entry with - Date far in the past (ie 2024-01-01) - Account: "400000 Customers", Partner: "test partner", Debit: 500.0 - Account: "499000 Suspense Accounts", Credit: 500.0 - Post - In Customers > Follow-up reports, the partner is marked as "In need of action" even if no due date was specified - Accounting Dashboard > Bank > new with Amount: 500.0 - "Save & Close" then click on it - In the page "Manual Operations" change the partner to the one from the MISC entry - Change the Account to "400000 Customers" - Validate - The follow-up report is no longer "In need of action" - Create an invoice with a due date in the future - The follow-up report is back to "In need of action" with the amount of the invoice - When sending the follow-up, the Customer statement reads "your account shows an outstanding balance of 0.00€" ### Cause: The origin of this issue is that the MISC entry and the Bank payment are not reconciled. The MISC entry is used to calculate the state of the followup making it to "In need of action" but the bank entry is balancing the amount to 0.00€. The MISC entry should not be used to compute the followup state as it has no due date specified (it makes no sense, it is never linked to any invoice). But in the code when there are no `line.date_maturity` we fallback on `line.date`. ### Solution: The lines without due date or payment term should not be used to compute the state of the followup or calculate the total due. So we remove the fallbacks on `line.date` when `line.date_maturity` is False. Some tests needed to be adjusted as they were not using any payment terms or due date. They were working because of the fallback on `line.date`. opw-4784250
Sales orders now calculate unit prices correctly when a branch company sells products whose taxes are defined on the parent company. This prevents incorrect untaxed pricing when fiscal positions switch between tax-included and tax-excluded sales taxes.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Set up 10% price-included tax; 2. copy the tax to a B2B version that's price-excluded; 3. create a B2B fiscal position mapping the first tax to the second; 4. create a $10 product using the first tax; 5. create a branch for the current company; 6. switch to the branch company; 7. set up a sale order with the fiscal position; 8. add the product to the order. Issue ----- While the line displays the correct B2B tax, the unit price displays $10, as if it was computed without any taxes, instead of a price-excluded tax. Cause ----- In the `_compute_price_unit` method, it filters out all tax records linked to the product that don't have the same company as the order line, so the parent company's tax does not get factored in. Solution -------- Rather than requiring strict equality between companies, also allow taxes that belong to a parent company of the line's company. opw-4853042 Forward-Port-Of: odoo/odoo#216124
Vendor payments now keep their original payment number when they are edited and posted again, even when an outstanding payments account is configured. This prevents unexpected numbering gaps or changes, helping accounting teams maintain consistent records and audit trails.
Original PR description
**Issue** When modifying and reposting a vendor payment that does not have the highest sequence number, the payment's name (i.e., number) is regenerated using the next available sequence, rather than…
**Issue** When modifying and reposting a vendor payment that does not have the highest sequence number, the payment's name (i.e., number) is regenerated using the next available sequence, rather than preserving the original. This issue only occurs when the Outstanding Payments account is configured for the journal. **Steps to Reproduce** 1.Install the Accounting module. 2.Go to Accounting > Configuration > Journals, and open a Bank journal. 3.In the Outgoing Payments tab, set an Outstanding Payments Account. 4.Go to Accounting > Vendors > Payments. 5.Create and post two vendor payments (e.g., 00001 and 00002). 6.Reset the first one (00001) to draft, change any field (e.g., amount), and repost it. 7.The number changes to 00003 instead of preserving 00001. **Root Cause** When a vendor payment is modified and reposted, Odoo cancels and regenerates the associated account.move. If an Outstanding Payments account is configured — or was configured at any point — this triggers additional logic causing the move name to be reset to '/'. This placeholder indicates that the move is treated as if it were new, prompting Odoo to assign it the next number in the journal’s sequence. As a result, the payment loses its original number even though it conceptually refers to the same transaction. **Fix** The fix ensures the original number is preserved by restoring the payment's previous name only when it's clear that the move is being regenerated, not newly created. This is determined by checking that the move is linked to exactly one payment (i.e., a one-to-one relationship) and that its name is '/', indicating the move was regenerated. Opw-4805870 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Posting a final invoice linked to an unsubmitted down payment will now show a clear warning instead of crashing. This helps users complete the required ZATCA submission steps in the right order and supports Saudi e-invoicing compliance.
Original PR description
Description of the issue/feature this PR addresses: This PR fixes a crash that occurs when posting an invoice linked to a down payment that has not yet been submitted to ZATCA. The issue is caused by a missing l10n_sa_confirmation_datetime on the referenced prepayment move. Current behavior before PR: When the prepayment invoice is not ZATCA-posted, its l10n_sa_confirmation_datetime is False, causing a crash during UBL generation for the final invoice. It raises AssertionError: Datetime instance expected Desired behavior after PR is merged: The system will raise a clear ValidationError, notifying the user that the related prepayment must be successfully submitted to ZATCA before continuing. This prevents silent failures and ensures proper compliance. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Saudi e-invoicing flow now stops final invoices linked to unconfirmed prepayments with a clear message instead of crashing or producing invalid data. This helps users correct the prepayment submission first, supporting proper ZATCA sequencing and compliance.
Original PR description
Description of the issue/feature this PR addresses: Invoices linked to prepayments (down payments) crash during ZATCA UBL generation when the related prepayment invoice lacks a l10n_sa_confirmation_datetime. This happens when the prepayment has not yet been successfully submitted to ZATCA. Current behavior before PR: If a prepayment is missing the confirmation datetime, posting the final invoice results in an error or invalid QR/UBL structure, with no clear user guidance. Desired behavior after PR is merged: The system raises a clear ValidationError instructing the user to first post the related prepayment to ZATCA. This prevents crashes and ensures proper invoice sequencing and compliance. I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Chilean electronic factoring files now always report the assigned invoice amount in Chilean pesos, even when the invoice uses another currency. This prevents incorrect AEC documents being sent or downloaded for Chilean invoicing workflows.
Original PR description
In this bug, when a currency other than CLP is selected in invoicing, the generated aec has MontoCesion tag with the rate of selected currency, while it must always be in CLP. To reproduce the bug: 1- Create a database with invoice app and a Chilean company 2- Create an invoice with document type of 34 3- Choose a different currency than CLP 3- Click on `Send Now to SII` and Create AEC 4- Click on Yield Entry smart button 5- Download generated AEC xml file 6- You can see the value of MontoCesion is in selected currency which is wrong opw-4830957
Rental orders using material resources now correctly count their planned shifts when calculating planning status. This prevents already-planned rental services from incorrectly showing as still needing planning, reducing confusion for sales and operations teams.
Original PR description
_*= sale_planning, sale_renting_planning Steps to Reproduce: - Install the `sale_renting_planning` module. - Create a rental product with the `Plan Service` enabled and the resource type set to…
_*= sale_planning, sale_renting_planning Steps to Reproduce: - Install the `sale_renting_planning` module. - Create a rental product with the `Plan Service` enabled and the resource type set to `Material`. - Create a SO for the newly created product and confirm it. - Observe the state button the shift is already planned but it incorrectly displays `To Plan`. Issue: - Confirming the SO the shift is already planned but the state button still displays `To Plan`. this issue occurs when the resource type is `Material` However it works correctly when the resource type is `User`. Cause: - When we are calculating the planned hours the domain `'resource_type', '!=', 'material'` is passed causes resources type of Material so it will be excluded from the calculation. Fix: - In this commit removed the condition that excluded resources of type Material so that they are included when calculating the planned hours. This ensures the state button shows the correct status. task-3978597
This fix ensures the journal smart button remains visible when creating accounting entries for individual payslips within a batch. Payroll users can now access the related journal entry even when other payslips in the same batch are not yet completed.
Original PR description
**Steps:** - Install the hr_payroll_account module - Navigate to the payroll menu and open a batch payslip. - Select a batch containing two or more payslips and create a draft entry for any single payslip in the batch. --- **Description of the issue/feature this PR addresses:** When a draft entry is created for a single payslip within a batch, the journal smart button becomes invisible. --- **Cause:** The issue occurs during the account move creation process. When generating an account move for a batch payslip, the process checks the status of all payslips in the batch. If any payslip is not in the done state, the account move is not created, resulting in the journal smart button not appearing. --- **Fix:** This PR adjusts the account move creation logic to allow account moves to be created for batch payslips, ensuring the journal smart button remains visible even if some payslips are not in the done state. task-4440533
The French FEC import now preserves the existing names of accounts when importing files that contain multiple accounts with similar codes. This prevents unintended renaming of accounts and helps keep financial records accurate after import.
Original PR description
Steps to reproduce: - import a fec with different account 164*** with different names Issue: All the account's name will be overriden Cause: Before 18.0, apparently, code and name were joined and was not an issue solution: update the code to the new logic by filtering out the name from the override (`_apply_template`) opw-4690284