Daily updates from Odoo
Friday, August 1, 2025
25 changes · saas-18.3
Resolved issues and error corrections
The stock report now treats tiny rounding leftovers as zero when calculating average cost. This prevents misleading, extremely large unit costs from appearing and gives users more accurate inventory valuation information.
Original PR description
## Before this commit: Opening the stock report displays gigantic unit cost in some cases, when the sum of the valuation's quantity is near zero but not exactly, due to float arithmetics. For example, if the total quantity is 1e-15 and the total value is $0.01, the average cost will display $10000000000000 instead of $0. ## After this commit: Use `float_is_zero` to correctly detect zero-ish quantity. opw-4869588 Forward-Port-Of: odoo/odoo#221062 Forward-Port-Of: odoo/odoo#218671
Corrects how future time off balances are calculated when unused days can carry over for a limited period. Employees and HR teams will now see the correct available leave after carryover days expire, avoiding misleading zero or partial balances in future balance checks.
Original PR description
### Steps to reproduce: - Create an accrual plan with the following rule: — The employee has 20 days off in the first year. Total 20. — The employee has 21 days off in the second year and an…
### Steps to reproduce: - Create an accrual plan with the following rule: — The employee has 20 days off in the first year. Total 20. — The employee has 21 days off in the second year and an additional 5 days off if available from the previous year, which can be taken until 6 months. Total 21 + 5 = 26 — The employee has 22 days off in the third year and an additional 5 days off if available from the previous year, which can be taken until 6 months. Total 22 + 5 = 27 — The employee has 23 days off in the fourth year and an additional 5 days off if available from the previous year, which can be taken until 6 months. Total 23 + 5 = 28 - Create an accrual allocation with the created plan - Check future allocation data using 'Balance at the' - Notice the following behaviour: — until 31/12/2025 it CORRECTLY shows 20 days available. — from 01/01/2026 to 30/06/2026 it CORRECTLY shows 26 days (21 days for renewal and 5 days not used in 2025) — from 01/07/2026 it INCORRECTLY shows no days available. — from 01/01/2027 to 30/06/2027 it CORRECTLY shows 27 days (22 days for renewal and 5 days not used in 2026) — from 01/07/2027 it INCORRECTLY shows 5 days. — from 01/01/2028 to 30/06/2028 it CORRECTLY shows 28 days (23 days for renewal and 5 days not used in 2027) — from 01/07/2028 it INCORRECTLY shows no days available. — from 01/01/2029 it CORRECTLY shows 28 days again. — In the following years, after 6 months, one year shows 5 days and the next shows nothing. ### Cause: The first cause here is that when we have validity for the carryover then we will have two calls in each year one at the start of the year and another at the expiration date of the carryover. So, when we add the days to the allocation we don't consider the second call in the condition and we only check if the allocation.actual_lastcall is equal to one of the start dates for each year https://github.com/odoo/odoo/blob/3fb37cbc59adc2caace8efcdae418d2466a9b750/addons/hr_holidays/models/hr_leave_allocation.py#L588 The second cause where each two years one of them shows the number of carryover days from the previous year, this is happening because when we remove the expiring days for the first year we set the number of days to 0 https://github.com/odoo/odoo/blob/3fb37cbc59adc2caace8efcdae418d2466a9b750/addons/hr_holidays/models/hr_leave_allocation.py#L516-L517 And it will be 0 until we loop again and add the days to allocation https://github.com/odoo/odoo/blob/3fb37cbc59adc2caace8efcdae418d2466a9b750/addons/hr_holidays/models/hr_leave_allocation.py#L521-L522 and since this is happening after we already set the expiring days which in this year will be 0 we won't remove those expiring days from the year's allocation data ### Fix: We add a condition to check if the actual_lastcall is either a date in the start of the allocation or one of the expiration dates for the carryover. Also, before we set the value of the expiring_carryover_days we call _add_days_to_allocation to calculate on the correct number of days for the plan level we are checking. opw-4606886 Forward-Port-Of: odoo/odoo#221248 Forward-Port-Of: odoo/odoo#209669
Invoice line rounding differences are now spread evenly across lines instead of being applied to one large line. This helps electronic invoices meet PEPPOL/BIS3 validation rules and reduces the risk of rejected invoices due to rounding discrepancies.
Original PR description
Before this commit, the behaviour of `_round_base_lines_tax_details` was to assign all the base line delta to the largest base line. However, when generating the UBL, the delta would then get included in the LineExtensionAmount, but BIS3 rule PEPPOL-EN16931-R120 enforces that the LineExtensionAmount must be at most 2 cents away from `(quantity * net price) + sum(charges) - sum(allowances)`. Effectively this means that we can put at most 2 cents base delta on each invoice line. After this commit, `_round_base_lines_tax_details` redistributes the base delta evenly over all the base lines. task-none Forward-Port-Of: odoo/odoo#220701 Forward-Port-Of: odoo/odoo#219244
Confirming a sales order for a service that creates a project now correctly assigns the customer's company when the project template has no company set. This prevents an unexpected error and lets businesses create project-based work from sales orders without manual data cleanup.
Original PR description
Currently, a user error occurs when confirming a Sales Order (SO). **Steps to reproduce:** 1) Install sale_project 2) Create a service product that generates a project and a task. 3) Add a project…
Currently, a user error occurs when confirming a Sales Order (SO). **Steps to reproduce:** 1) Install sale_project 2) Create a service product that generates a project and a task. 3) Add a project template by creating one from the product form view. 4) Create an SO by creating a customer with a company 5) Add the above-created service product and confirm the SO. **Error:** A user exception will be triggered ``` The project and the associated partner must be linked to the same company. ``` **Cause:** - When a project template is created from the product view, both the customer and the company_id default to empty. - Later, when confirming a SO with a customer that belongs to a company, the new project's company_id is taken from the project template, which is empty. https://github.com/odoo/odoo/blob/876e9d5e9ba87fa69188b2da098eec78f77040f5/addons/sale_project/models/sale_order.py#L140-L141 - However, the project’s partner_id (the customer) does have a company_id, (since the customer value for the project will be set through SO's customer). - This leads to a mismatch between the project’s company_id(which is empty) and its partner’s company_id. So a user exception will be triggered from the below lines https://github.com/odoo/odoo/blob/876e9d5e9ba87fa69188b2da098eec78f77040f5/addons/project/models/project_project.py#L257-L258 **Solution:** - If the project template has no company_id, and the customer of the project has one, set the project’s company_id to match that of the customer. opw-4900741,4880495 Forward-Port-Of: odoo/odoo#216582
This fixes a Spanish accounting setup issue where two domestic fiscal positions existed after an upgrade. The duplicate Mainland Spain entry is merged into ES Domestic, reducing confusion and helping ensure taxes are applied consistently.
Original PR description
Before this commit: - In version 18.3, due to changes and migrations in fiscal positions, the domestic fiscal position for Spain was duplicated (ES Domestic and Mainland Spain). After this commit: - Merged the duplicated fiscal position 'Mainland Spain' into 'ES Domestic'. task-4972464
Opening an invoice could fail when related credit notes and statement lines existed for the same partner. The accounting calculation was adjusted so the outstanding credits and debits information is computed independently, preventing the error and keeping invoice payment information available.
Original PR description
To reproduce: - Install account_accountant (not reproducible on runbot with all modules installed) - Create an invoice for partner_a - Create a credit note for same partner - Create a statement line for same partner - Open the invoice => Traceback The issue is that invoice_outstanding_credits_debits_widget is first put to False, then protected. So the real value is not put, while invoice_has_outstanding is changed. So in the override of the compute, it does not contain 'content' (=False), and so fails. The issue is not easy to solve. Problem of cache protection etc,... The situation does not seem problematic per se. We separate the 2 fields in 2 compute, so invoice_outstanding_credits_debits_widget is not protected by the computation of invoice_has_outstanding --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Timesheet administrators who do not have Project app access can now open timesheet lists and related forms without being blocked by access errors. This keeps timesheet review workflows working while preserving normal project record permissions.
Original PR description
Steps to Reproduce: - Ensure the `sale_timesheet` module is installed. - Log in as a user with Timesheet Administrator permissions but without access to the Project module. - Attempt to open the…
Steps to Reproduce: - Ensure the `sale_timesheet` module is installed. - Log in as a user with Timesheet Administrator permissions but without access to the Project module. - Attempt to open the Timesheets list view results in an `AccessError` due to missing read rights on `project.task`. - Create a task in a private project linked to a timesheet and open its form view results in an `AccessError` due to missing read rights on `project.project`. Cause: - When a user has Timesheet Administrator access but lacks project access, they can view all timesheets, including those linked to tasks with private privacy visibility. However, these users do not have read access to the private tasks themselves. - The `_compute_commercial_partner` method reads `task_id.partner_id.commercial_partner_id` and `project_id.partner_id.commercial_partner_id`. When a user without read access to `project.task` or `project.project` tries to compute this field, an `AccessError` occurs because the code tries to access these related records without bypassing access rights. Solution: - Use `sudo()` on `task_id` and `project_id` when accessing their `partner_id` fields inside the compute method to bypass access rights checks, preventing ` AccessError` for users lacking read permissions. task-4798066 Forward-Port-Of: odoo/odoo#221247 Forward-Port-Of: odoo/odoo#210826
Alerts shown when a recipient is missing an email address now remain visible instead of being covered by the recipient prompt. This makes the sending flow clearer and prevents users from missing important guidance.
Original PR description
## Before this commit When the user clicks the Send button and the partner does not have an email address, an alert message is raised. However, the recipient popover `(email input prompt)` appears above the alert, visually blocking it and breaking the expected `modal` behavior. <img width="1844" height="873" alt="image" src="https://github.com/user-attachments/assets/31585785-27d6-48d4-b64c-c88b5f9426d6" /> ## After this commit The recipient popover's `z-index` is adjusted so that it no longer overlaps alert messages. This ensures that alerts remain visible and unobstructed, preserving clarity in the UI and respecting the intended visual hierarchy. <img width="1736" height="764" alt="image" src="https://github.com/user-attachments/assets/9ff258b4-2072-4100-bcc4-b8420d5d1aa2" />
Fixed an issue where collaborator avatars could overlap the status bar buttons while scrolling long form content. This keeps important actions visible and makes collaborative editing smoother for users.
Original PR description
User avatars displayed in collaborative mode overlap with buttons when scrolling. This commit extends the statusbar to take the full width, independently of the sheet's one. Also, to avoid an ugly shadow when not scrolling, it only adds it when the scroll is actually performed. Steps to reproduce: - open a task with two users - write in the description in collaborative mode -> user avatars should be displayed - make sure the description is long enough for the sheet to scroll - scroll for one of the avatars to reach the sticky statusbar => overlap between the avatar and the statusbar task-4907797 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale now correctly accepts multiple existing serial numbers on the same order line when creating new serial numbers is disabled. This prevents valid sales from being blocked when cashiers add several serialized units of the same product.
Original PR description
**Steps to reproduce:** - Install `point_of_sale`. - Go to POS -> configuration -> settings - Search 'Operation type' -> open picking type -> Disable `Create new` - Create a storable product 'test'…
**Steps to reproduce:** - Install `point_of_sale`. - Go to POS -> configuration -> settings - Search 'Operation type' -> open picking type -> Disable `Create new` - Create a storable product 'test' with serial tracking. - Add on-hand quantity with serial numbers. - In POS, select the product and choose one SN, - Select it again and choose another SN. **Observation:** - The order line should have 2 quantities with a list of Serial numbers chosen by the user. For one quantity, it's working fine, but for multiple quantities, an issue occurs. **Issue:** - While confirming edit serial numbers popup for multiple quantities, it checks whether each selected SN is valid or not. - The condition is that the entered SN is in the existing available SNs option. But the already chosen SN is not in the existing SN option, - Also, creating a new SN is disabled, so it's considered an invalid input. https://github.com/odoo/odoo/blob/876b7337eb689e0682ab48e9e833f9f0dc6bb8d2/addons/point_of_sale/static/src/app/store/select_lot_popup/select_lot_popup.js#L190-L193 **Solution:** - Added a condition to allow SNs that are already selected (matched by name and ID) to be considered valid inputs. opw-4865902 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220932 Forward-Port-Of: odoo/odoo#219205
This fix ensures invoice legal document retrieval consistently returns the expected data format, preventing errors in related download flows. It also improves support for downloading invoice documents across multiple file types, making document access more reliable for accounting users.
Original PR description
`_get_invoice_legal_documents` should, and is expected to, return a dict. however, if called with `filetype = all`, it returns, because of `_get_invoice_legal_documents_all`, a list which breaks calling code as they expect a dict not a list, and this part of the code is not used anywhere nor tested. - remove the line causing `_get_invoice_legal_documents` to return a list. - make `download_invoice_documents_filetype` work with multiple filetypes no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221267 Forward-Port-Of: odoo/odoo#220170
Clicking a non-translatable page element in website translation mode now shows the warning only once. This avoids duplicate notifications and makes the translation editing experience clearer for users.
Original PR description
Since [1], when clicking a non-translatable element in translation mode, the notification was sometimes shown multiple times due to event bubbling. This commit stops the click event from propagating, ensuring the notification is only triggered once. [1]: https://github.com/odoo/odoo/commit/41e341177611cf69d1bd61e66a809510c22cc1b7 Forward-Port-Of: odoo/odoo#221241
This fix helps Point of Sale recover correctly after a temporary internet outage. When the connection comes back, the system now waits briefly before checking connectivity and then triggers order synchronization, reducing the risk of sales data staying unsent.
Original PR description
Steps to reproduce: - open a pos on a runbot from saas-18.2 - turn off the wifi on your device until you see the disconnected sign - turn back on the wifi - the pos stays in "offline" mode Issue: The ping rpc call is made before the connection is really reestablished. The rpc call fails and the network.offline attribute stays true. This prevent the data from being sent to the backend. Fix: Set a timeout to perform the ping rpc call and sent an envent to notify the pos_store to syncAllOrders when back online. Task-id: 4978122 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#220954
This change restores correct backorder handling when a delivery includes both regular and subcontracted products. It avoids blocking barcode users in a situation where they had no practical workaround, while keeping test coverage for the barcode flow.
Original PR description
This commit reverts db8b33e (and the wrong follow-up fix of 2755c09) because it breaks backorders for pickings that mix regular and subcontrcted products. We'd rather the flow has problems in back end where the user can manually uncheck the picked box rather than in barcode where there is no work around. We keep the enterprise test introduced in [792c968](https://github.com/odoo/enterprise/commit/792c968) to protect the barcode flow. Forward-Port-Of: odoo/odoo#220318
Creating a parent task directly from an existing task now automatically assigns it to the same project. This prevents parent tasks from being created without project information and also avoids showing the parent task option for private tasks where it should not apply.
Original PR description
Before this commit, when the user creates a parent task on the fly in the list view of tasks or even in the form view of task, the parent task creates does not have the project of the task by default. This commit adds the project of the task as default value for the new parent task when the user creates a parent task in the parent_id field. Steps to reproduce the issue ---------------------------- 0. Install project. 1. Go to Projects > All tasks. 2. Show the parent task field. 3. Edit the parent_id field in the list view of an existing to create a new parent task. 4. Go to form view of the parent task Expected Behavior ----------------- The parent task should have the same project than the task in which we create the parent task. Current Behavior ---------------- The parent task created has no project set by default. task-4781342 Forward-Port-Of: odoo/odoo#220995 Forward-Port-Of: odoo/odoo#209434
Task checklist items now keep their checked or unchecked state when users leave the task via breadcrumbs. This prevents lost updates in project task descriptions and makes checklist tracking more dependable.
Original PR description
Problem: In the Project app, when a task's description contains checkboxes and you check an item, then navigate back using breadcrumbs, the change is not saved. Cause: Breadcrumb navigation triggers a `blur` event to save the content. However, if the editable is not focused and you click on a checkbox, it doesn’t focus the editable. As a result, clicking away does not trigger `blur`, and the change is lost. Solution: Since `<li>` elements are not focusable, we programmatically focus the editable when toggling a checkbox. If it was already focused, we preserve the current selection. Steps to reproduce: - Add checkboxes to a task description - Save - Mark one checkbox as checked (editable remains unfocused) - Navigate back using breadcrumbs - Open the same task again -> The checkbox state is not saved opw-4922375 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219891
This fixes an issue in the website form editor where a field's default value could disappear after changing the field's position and visibility. Businesses can now edit website forms with more confidence that preset form values will be preserved.
Original PR description
Problem: When changing the default value of a field, then modifying its position and visibility, the field loses its default value. Cause: Setting a default value assigns the `value` attribute to the…
Problem:
When changing the default value of a field, then modifying its
position and visibility, the field loses its default value.
Cause:
Setting a default value assigns the `value` attribute to the field's
input element. However, after re-rendering with `_renderField`, the
HTML `value` attribute is lost. As a result, when
`_computeWidgetState` called with `selectAttribute` as method name, it
fails to retrieve the value because there is no HTML `value` attribute
on the input.
Using `t-att-value="field.value"` will lead to `value` attribute loss
during owl rendering, this is an owl bug but this fix is to work around
it until it is globally fixed.
Solution:
use `t-attf-value="#{field.value}"` instead of
`t-att-value="field.value"`
Steps to reproduce:
- Add a form
- Select any input field
- Set a default value
- Change the field's position
- Change the field's visibility
-> The default value is lost
opw-4902544
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#220047This fix prevents PDF print jobs on Android devices from being stopped too early while the print preview is still loading. It improves reliability for users printing documents from mobile browsers, reducing failed or incomplete print attempts.
Original PR description
Currently, pdf.js does not support printing from mobile browsers, and the pdf.js team will not fix this issue [1]. I investigated and found that sometimes `window.print()` is asynchronous [2]. On Android, the print preview dialog re-renders the entire PDF within the preview, which can obviously take some time and the abort method is call before the preview rendering is complete. opw-4190135 [1]: https://github.com/mozilla/pdf.js/issues/12020 [2]: https://github.com/mozilla/pdf.js/blob/2d0ba7db08fb6bb597ba718635314d8e8998a7d0/web/pdf_print_service.js#L226 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221172 Forward-Port-Of: odoo/odoo#217526
Users can now change dates for recurring shifts in Sale Planning without hitting a missing record error. The fix ensures Sale Planning only updates shifts that still exist after Planning processes the recurrence change, preventing disruptions when editing all shifts.
Original PR description
Version: 17.0 Steps to reproduce: - Install sale_planning - Create a recurrence shift. - Change the date of second shift which is created by recurrence. - Give the edit value as All shifts. - save record, missing error occured. Issue: When a user changes the date of a shift created by recurrence, the system crash with the message, "Record does not exist or has been deleted." Cause: There was an issue between "Planning" and "Sale Planning". When a user moves a shift, "Planning" removes the old shift from the system except the first one, But 'sale planning' was still trying to work with that removed shift. Fix: Now, after 'Planning' does its work, 'Sale Planning' checks again to see that shifts are still there. It only works with shifts that actually exist. So crash no longer happens. Users can now safely change the date of recurring shifts without errors. task-4859892 Forward-Port-Of: odoo/enterprise#91236 Forward-Port-Of: odoo/enterprise#88234
This fix corrects how the Accounting app calculates whether an invoice has outstanding amounts. It helps prevent incorrect invoice status information from being shown or updated, supporting more accurate accounting workflows.
Original PR description
We separated the compute method for the 2 fields. The override of the compute should not compute invoice_has_outstanding anymore.
Timesheet administrators who do not have Project access can now open the Timesheets list and kanban views without hitting an access error. This prevents a blocking issue for managers who need to review timesheets but should not have broader project permissions.
Original PR description
Steps to Reproduce: - Ensure the `timesheet_grid_holidays` module is installed. - Log in as a user with Timesheets Administrator access but no access to the Project module. - Navigate to the Timesheets > List or Kanban view. - An `AccessError` occurs due to missing read rights on the `project.task` model. Cause: - In the `timesheet_grid_holidays` module, the `_should_not_display_timer` method accesses `self.task_id.is_timeoff_task` without checking access rights, causing an `AccessError` when users who can view timesheets but lack read access to `project.task` try to access tasks linked to projects with private privacy visibility. Solution: - Use `sudo()` when accessing `self.task_id` in `_should_not_display_timer()` to avoid access errors. task-4798066 Forward-Port-Of: odoo/enterprise#91361 Forward-Port-Of: odoo/enterprise#86302
Manufacturing users who are not HR users can now open the Shop Floor app without an access rights error. Employee barcode lookup is handled only when needed, avoiding restricted HR data access while preserving barcode identification on the shop floor.
Original PR description
**PROBLEM** If a user is in the mrp.group_mrp_user group, but does not belong to hr.group_hr_user, he can't access the shop floor app. **STEP TO REPRODUCE** 1. connect with a user which is a user of manufactring, but not a user of hr. 2. try to go on the shop floor app and notice there is an access right error. **CAUSE** When connecting to the shop floor app, we are trying to get the barcode field on all employee (because we need them if we want to identify an employee on the shop floor app using their barcode). This was added in this commit: https://github.com/odoo/enterprise/commit/b3fb0073a15adcc799a5681284f0cfd2308764b8 The barcode field is only accessible to member of hr.group_hr_user. **FIX** Instead of getting the barcode of all employee using `get_all_employee()`, we do a rpc call to query the employee the barcode belong to. opw-4905206
The French VAT return export now places repayment amounts from grid 26 in the correct XML field. This prevents missing or misplaced reimbursement amounts when submitting the VAT return electronically.
Original PR description
The French VAT report line for grid 26 ("Repayment of credit requested on form n°3519") uses code `box_26_external`, but the XML generator only mapped `box_26` to the `JB` tag.
As a result, the reimbursement amount was missing or incorrectly placed in the XML file.
This commit maps `box_26_external` to `JB` to ensure the correct tag is used when the user fills in grid 26.
opw-4931275
Forward-Port-Of: odoo/enterprise#90940This fixes how absence-related days are calculated in Swiss payroll reporting. It helps ensure payroll and statutory declarations use accurate day counts, reducing the risk of incorrect employee records or reporting adjustments.
Original PR description
Forward-Port-Of: odoo/enterprise#91391 Forward-Port-Of: odoo/enterprise#91358
Payslip PDFs now correctly follow the salary structure setting that hides the basic wage. This prevents confidential wage details from appearing when the option is enabled, matching the expected payroll configuration.
Original PR description
After this commit: odoo/enterprise@9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048…
After this commit: odoo/enterprise@9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048 [diff](https://github.com/odoo/enterprise/commit/9dceed0896ce5089bccbc9cc2ce1e8c4b13f0048#diff-de4a628e7837c273b67d71f93efab85b6a9ee957ea702f502066ebcc632a76cbL64) The condition that handles hiding the basic wage on the payslip was not added —possibly it was missed. That’s why the "Hide basic on PDF" feature doesn’t work, regardless of whether it’s enabled, as the necessary condition is missing in the template. Steps to reproduce (on runbot): - In a v18 runbot, open any payslip and go to the salary structure. Enable the "Hide basic on PDF" option. - Return to the payslip and print it. - You’ll see that the basic wage is still printed on the payslip. **Before Fix:** <img width="669" height="238" alt="payslipbefore" src="https://github.com/user-attachments/assets/2fce67a2-19d8-45d8-88fa-4fc6a1767e68" /> **After Fix:** <img width="683" height="289" alt="payslipafter" src="https://github.com/user-attachments/assets/adcb0104-9c4e-4a35-ba78-b3f278f6bfda" /> opw-4953831 Forward-Port-Of: odoo/enterprise#90798