Daily updates from Odoo
Tuesday, March 24, 2026
58 changes · saas-19.2
Resolved issues and error corrections
This update fixes a bug where right-clicking on keypad buttons incorrectly triggered a long-press action. This issue stemmed from the way the context menu was handled, leading to unintended behavior. The fix ensures that only left-button actions are recognized, improving the overall user experience.
Original PR description
Since [1], some keypad buttons have a long-press value/action and, at worst, they enter the normal key value after the long-press duration. It was later improved by [2] (19.2) and other actions were…
Since [1], some keypad buttons have a long-press value/action and, at worst, they enter the normal key value after the long-press duration. It was later improved by [2] (19.2) and other actions were added such as long-pressing backspace at [3] (19.2) and more recently [4] (19.3) which allows calling the voicemail with long-pressing "1". In all those versions and features, there is the same bug: right-clicking the key triggers the long-press action as the context menu opens over the cursor, then our implementation ends up believing a long-press was performed. Solution: we should never have considered anything else than left-button actions anyways. [1]: https://github.com/odoo/enterprise/commit/82b4c4327fc722f55a0c14b14a916a5cddafa0eb [2]: https://github.com/odoo/enterprise/commit/b9dd0d6fc1fee479e9c8cd4c89dc0a9147891185 [3]: https://github.com/odoo/enterprise/commit/2723ef65622bb206d64e08482f3acd6594c03d28 [4]: https://github.com/odoo/enterprise/commit/dea0baa0dfd76962865717173807e4c945414cd3 task-6055182 Forward-Port-Of: odoo/enterprise#111490
This update fixes a technical error that occurred when users tried to take pictures without an IoT device connected to a quality control point. The fix adds a check to ensure a device is set, preventing a system error and guiding the user to properly configure the control point.
Original PR description
Currently, an error occurs when the user clicks the Take Picture button without an IoT box set on the quality control point. ## Steps to replicate: - Install Quality, Purchase, IoT - Quality >…
Currently, an error occurs when the user clicks the Take Picture button without an IoT box set on the quality control point. ## Steps to replicate: - Install Quality, Purchase, IoT - Quality > Quality Control > Control points - Create a new Control point with - Type: Take A Picture - Operations: My Company: Receipts - Create and confirm a purchase order for a test product - Receipts > Quality Checks > Take A picture ## Observed behavior: TypeError: Cannot read properties of undefined (reading '0') ## Root cause: This error occurs because no device has been set on the control point. When the user clicks the **Take a Picture** button, the `onClick` method [1] is triggered. Since `this.iotDevice` is false, both `iotBoxId` and `deviceIdentifier` are undefined. These undefined values are then passed to the action function [2], which in turn passes them to the `_attemptFallbacks` function. At [3], a type error occurs because the system tries to index `iotBoxId` even though it is undefined. [1]: https://github.com/odoo/enterprise/blob/2c2e358695357a730b66480fd99c27d7e922bd0b/quality_iot/static/src/iot_picture_button.js#L7-L17 [2]: https://github.com/odoo/enterprise/blob/2c2e358695357a730b66480fd99c27d7e922bd0b/iot/static/src/network_utils/iot_http_service.js#L213-L236 [3]: https://github.com/odoo/enterprise/blob/2c2e358695357a730b66480fd99c27d7e922bd0b/iot/static/src/network_utils/iot_http_service.js#L149-L152 [4]: https://github.com/odoo/enterprise/blob/1d25675de808521dc8ad8c56bc9fbd320a0ae56b/quality_iot/static/src/iot_measure_button.js#L27-L32 ## Solution: Add a check for an unset device and notify the user to add a device to the quality point. This prevents a traceback and clearly informs the user about the issue. Similar to how it was done in [4] opw-6010095 Forward-Port-Of: odoo/enterprise#110615
This update fixes a discrepancy in test data related to tax reporting for foreign customers in Ecuador. The system now correctly identifies company partners ('02' tipoCliente) based on a new internal field, ensuring accurate tax calculations and compliance with Ecuadorian regulations. This change improves the reliability of reports generated for international sales.
Original PR description
Since `tipoCliente` is now determined using the computed `is_company` field, the test data must reflect this logic. `partner_ext` represents a foreign partner and is considered a company, therefore its `tipoCliente` should be set to '02'. See: https://github.com/odoo/enterprise/commit/a779badac35cf4a8f483f490e8ae29eb6bf3d2c5 `l10n_ar_edi`: For foreign partners, AFIP requires the CUIT pais based on the partner’s country and document type, not on partner.is_company. In multi-localization databases, is_company may be influenced by local heuristics and lead to picking the wrong foreign tax identifier. Use the identification type instead: VAT documents map to the legal-entity CUIT pais, while non-VAT documents map to the natural-person one. See: https://github.com/odoo/enterprise/pull/86089#discussion_r2128977870 runbot-241126 Forward-Port-Of: odoo/enterprise#110055
This update fixes an issue where the 281.50 PDF report occasionally generated an extra page due to formatting. The change optimizes the report layout to ensure it consistently uses only one page for standard reports, improving readability and reducing unnecessary PDF sizes. This primarily impacts reports for Belgian companies.
Original PR description
**Behavior:** Currently when generating the 281.50 report the pdf ends up taking an extra page filled only with header and footer, the page appears when creating the report for a natural person and…
**Behavior:** Currently when generating the 281.50 report the pdf ends up taking an extra page filled only with header and footer, the page appears when creating the report for a natural person and adding a national number. The solution is not to fully prevent the report form being more than 1 page long, as some informations could span over more than one line which would make the pdf need an extra page. But to shave a few milimeters so that by default when filled with standard informations the pdf appears cleaner. **Steps to reproduce:** - Log to a Belgian company - Create a contact that is a person - Add the 281.50 tag to them - Create a credit note for any positive amount for that person and set the date to the previous year - Make sure the account used in the credit note has any 281.50 x tag assigned - Go to Accounting/Reporting/Open 325 forms and create a new form for the year indicated in the credit note - When generating the 281.50 PDF you'll seee it span over 2 pages if you have filled the national number of the contact opw-5930339 Forward-Port-Of: odoo/enterprise#111310
This update fixes a critical issue where signature deadlines weren't updating correctly, leading to outdated task reminders. It also ensures that 'Signature Request' activities are automatically removed when a request is canceled, preventing clutter and improving the user experience. The change includes a safeguard to prevent errors when canceling directly from the activity widget.
Original PR description
1. **Date Sync: mail.activity & sign.request** **Before Fix:** When the validity_date on a sign.request was updated, the linked mail.activity (the "Please Sign" task) did not update its deadline.…
1. **Date Sync: mail.activity & sign.request**
**Before Fix:** When the validity_date on a sign.request was updated, the linked mail.activity (the "Please Sign" task) did not update its deadline. This led to a discrepancy where a document might expire in 2 days, but the user's to-do list still showed a deadline from a week ago.
**Expected Behavior:** The activity deadline should always reflect the current validity of the document to ensure signers are aware of the actual remaining time.
**Fix:** Overrode the write method on sign.request. When the validity_date is modified, the system now automatically updates the date_deadline of all associated records in sign_activity_ids.
2. **Activity Cleanup on Cancel**
**Before Fix:** Canceling a sign.request changed the document state but left "Signature Request" activities sitting in users' to-do lists. This resulted in "orphan" activities that pointed to canceled documents, cluttering the chatter and the activity bin.
**Expected Behavior:** Canceling a request should globally clean up any pending tasks related to that specific request.
**Fix:** Updated the cancel method to unlink associated activities.
**Note on Conflict Prevention:** To avoid a UserError/MissingRecord when canceling directly from the activity widget (where the interface attempts to delete the activity immediately after calling the cancel method), a context flag skip_sign_activity_unlink was introduced. This ensures that if the activity is already handling its own deletion, the backend doesn't "double-delete" it.
Task: 5989542This update ensures the 'Mark as Complete' button is always visible when a return flow has been started, regardless of the user's connection preferences or temporary API issues. This resolves a previous issue where the button was hidden, preventing users from finalizing returns, particularly in localized versions or during API downtime.
Original PR description
When a flow is already started, the button "mark as complete" on returns was invisible. This is an issue for some localizations that don't handle the flow when the API connection is not desired by the user. Another use case, for example, is the API connection is down temporarily, the user manually uploads it on the website, then wants to close the started return. Forward-Port-Of: odoo/enterprise#111600
This update corrects a technical issue impacting UK customer top-ups. The system previously relied on outdated data location information, causing processing errors. This change ensures accurate top-up payments for UK accounts by aligning with the current payment structure.
Original PR description
Fix the UK top-up logic as UK accounts payload structure shifts from the EU where the country data is located in the EU payload it could be found under bank_transfer[financial_adresses][0][iban][country] and bank_transfer[country] but in the uk payload it can only be found in the second As we used the first one, we are now switching it to the second as it's the only common ground Forward-Port-Of: odoo/enterprise#111588
This update fixes an issue where linked records were lost when importing spreadsheets from CSV or XLSX files. The change ensures that newly created spreadsheet documents maintain the original linked record, improving data consistency and simplifying workflows. This resolves a bug impacting how spreadsheets are created and linked to other Odoo records.
Original PR description
When importing an XLSX or CSV document into a spreadsheet, the linked record is lost on the newly created spreadsheet document. This happens because the conversion creates a new document through `copy()`, while `res_model` and `res_id` are computed fields and are not copied by default. This commit explicitly forwards the linked record values during the conversion so the created spreadsheet keeps the same linked record as the source document. Task: [6008920](https://www.odoo.com/odoo/project/2328/tasks/6008920) Forward-Port-Of: odoo/enterprise#111532 Forward-Port-Of: odoo/enterprise#110047
This update fixes an issue where salary deductions weren't being accurately calculated for certain types of salaries (like 'ATTACH_SALARY') in the Kenyan payroll system. The changes ensure that these deductions are now correctly applied, leading to more precise net pay calculations for employees. This resolves a previous error impacting payroll accuracy.
Original PR description
**Behavior before this commit** Some salary rules (e.g. `ATTACH_SALARY`) were ignored in the NET calculation. **Behavior after this commit** - Four rules are now added to the "Total deductions" line: their sequence and category has been changed. - The sign of these lines has also been switched: an attachment of salary of a positive amount should be added to the amount of total deductions, which is then deducted from the net.  opw-5894647 Forward-Port-Of: odoo/enterprise#110579 Forward-Port-Of: odoo/enterprise#107033
A recent change has resolved an error that occurred when updating payroll data in the Saudi Arabian company setup. This fix prevents a data mismatch issue that arose when users deleted salary rule categories, ensuring the 'Payroll: Update Data' process runs smoothly. This improves the reliability of payroll processing for Saudi Arabian companies.
Original PR description
Currently, an error occurs when the "Payroll: Update Data" scheduled action is executed. **Steps to Reproduce:** - Install `l10n_sa_hr_payroll` with demo data. - Switch to `Saudi Arabian` company. -…
Currently, an error occurs when the "Payroll: Update Data" scheduled action is executed. **Steps to Reproduce:** - Install `l10n_sa_hr_payroll` with demo data. - Switch to `Saudi Arabian` company. - Go to `Payroll` > `Configuration` > `Salary` > `Rule Categories`. - Delete all records related to the Saudi Arabian company. - Go to `Scheduled Actions` and run `"Payroll: Update Data"`. `ValueError: External ID not found in the system: l10n_sa_hr_payroll.l10n_sa_category_provision` After [this commit], the category_id field becomes non-required, allowing users to delete a rule category record even if it is linked to a salary rule. When updating the data file [1], this causes an error due to the missing rule category [2]. This commit ensures that, when updating the salary rule data, the rule category data is updated beforehand, as shown here [3]. [this commit]: https://github.com/odoo/enterprise/commit/c663fd2a81b7f6b34f8199fdbdc4a75c4f21379e [1]- https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_sa_hr_payroll/models/hr_payslip.py#L157-L165 [2]: https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_sa_hr_payroll/data/hr_salary_rule_saudi_data.xml#L249 [3]: https://github.com/odoo/enterprise/blob/5ab4cb8bbf8211783a23a4334b633d52633b0324/l10n_ke_hr_payroll/models/hr_payslip.py#L9-L18 sentry-7349905716 Forward-Port-Of: odoo/enterprise#111438
This update fixes an issue where DATEV reports generated from Odoo were sometimes inaccurate due to incorrect account assignments. Now, when a move line's account is changed, the DATEV export automatically updates to reflect the new account, preventing duplicate lines in the export. This ensures accurate financial reporting to DATEV.
Original PR description
Description of the issue this commit addresses: When the account of a move line is updated (e.g. replacing the suspense account with the actual one), l10n_de_datev_main_account_id was not recomputed which leads to an incorrect DATEV export with duplicate lines. Desired behavior after this commit is merged: Changing the account_id of a move line recomputes l10n_de_datev_main_account_id so that the exported DATEV data reflects the current accounts of the move. Forward-Port-Of: odoo/enterprise#111493
This update fixes an issue where payroll moves with analytic distribution rules weren't properly anonymized, potentially exposing employee data. The change ensures that payroll moves are correctly aggregated and anonymized, maintaining privacy and compliance. A new test has been added to verify the fix.
Original PR description
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to…
The Batch Account Move Lines option in the settings is used to aggregate together the different payslips of a payrun and to create only one move with aggregated lines, per account. This is done to enforce privacy and avoid having lines for each employee in the payrun. If salary rules with analytic distributions are involved, though, the lines are not merged and we lose the anonimity.
This happens because in the _get_existing_lines funciton, that should return the lines to be merged with the input line (line), the condition for the rules that have an analytic distribution is wrong.
In particular, the condition is wrong because the
distribution_analytic_account_ids field is a recordset of the accounts, while line_id['analytic_distribution'] is a dictionary with keys that are comma separated strings of the ids of the accounts, with values reflecting the percentage.
For example, if a rule has one analytic distribution for 40% and involving accounts 13,7 and 12 + another analytic distribution for 60% involving accounts 3 and 5, line_id['analytic_distribution'] will be {'13,7,12': 40.0, '3,5': 60.0} while distribution_analytic_etc will be a recordset containing (13,7,12,3,5). To fix the problem and keep everything inline, we extract the logic to a new function, where we first unravel the ids from the keys of the dictionary and only then try to match them to the values in the recordset.
Task: 6043957
Forward-Port-Of: odoo/enterprise#111140A technical issue causing a tour to fail has been resolved. This change adjusted the company referenced within the tour, addressing a previously unreplicable access rights problem. The fix ensures the tour now runs correctly, improving the user experience.
Original PR description
Before this commit, the tour `hr_referral_utm_campaign_tour` was failing because of some weird access rights issues. The issue did not seem to be reproducible in local with similar condition. This commit changes the company used in that tour runbot issue 239152
This update resolves an issue with the format of Client IDs used in the payroll module, specifically addressing a change in how the 'chaman' expeditor number is represented. This ensures consistent data handling and avoids potential errors during payroll processing. The fix improves the reliability of the system for Belgian payroll calculations.
Original PR description
Forward-Port-Of: odoo/enterprise#111531 Forward-Port-Of: odoo/enterprise#111276
This update fixes a situation where the Gemini AI feature would sometimes fail to respond to users, appearing as a system error. The fix automatically retries the request with a slightly increased processing limit and, after three attempts, informs the user of the failure. This ensures a smoother and more reliable experience with the AI functionality.
Original PR description
It often occurs that gemini responses come back empty without anything to show to the users. Specifically, the response object has content but the "parts" are empty - the place were you either get a…
It often occurs that gemini responses come back empty without anything to show to the users. Specifically, the response object has content but the "parts" are empty - the place were you either get a function call or a message to the user by the LLM. Prior to this commit, when this occured, we didn't perform any explicit handling. We would always just return what the LLM responded with, which when empty would be nothing. UX wise, it would seem like something broke because the user would basically get no reply. In this commit, we add a retry mechanism in `_request_llm_google` of `llm_api_service.py`, where if we get no response, we increase the thinking budget of the next request to 512 and try again. 512 tokens were chosen completely arbitrarily - anecdotally, the model should use around 300 thinking tokens for its tasks so 512 should be enough. After 3 unsuccessful tries, we send a failure response to the user. Task-5959805 Forward-Port-Of: odoo/enterprise#111228 Forward-Port-Of: odoo/enterprise#108755
This update resolves issues related to incorrect overtime calculations when employees work across different time zones. Specifically, it ensures that overtime intervals are accurately determined based on the employee's local time, preventing crashes and ensuring correct overtime tracking. This improves the reliability of our HR attendance system.
Original PR description
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a…
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a period, then create two consecutive midnight-to-midnight attendances in the employee's local timezone. Creating the second attendance crashes with: "ValueError: Expected singleton: hr.attendance.overtime.line(...)". Steps to reproduce (stale overtime lines): With the same setup, delete the attendance after it generated overtime lines. The overtime lines remain in the database instead of being removed. The singleton crash occurred because `end_of_day` in `_get_overtime_intervals` was computed as a naive datetime, implicitly treated as UTC. For UTC+ timezones, the actual local end of day is earlier than UTC midnight. As a result, overtime intervals were computed with a stop time extending past the real local midnight into UTC time. When consecutive attendances were processed together, these extended intervals overlapped. The `Intervals` class (`keep_distinct=True`) merges overlapping intervals into a single entry with a multi-record recordset as payload. The subsequent `overtime.rule_ids.work_entry_type_id` and `overtime.status` calls expected a singleton but received a multi-record set, causing the crash. The same multi-record issue also affected the iteration in `_set_real_overtime_intervals` and the overtime work entry loop in `_get_attendance_intervals`. The stale overtime lines issue occurred because `_get_overtimes_to_update_domain` (hr_attendance) built its search date range from raw UTC `.date()` values instead of the employee's local timezone. For UTC+ employees whose attendance spans local midnight, the overtime line is dated in the next local calendar day. Since the domain was derived from UTC dates, that next local day fell outside the search range, so the overtime line was never found and deleted when the attendance was removed. Solution: - In `_get_overtime_intervals`, localize `end_of_day` to the employee's timezone before converting to UTC, so overtime intervals are correctly bounded by the local end of day. - In `_set_real_overtime_intervals` and the overtime loop in `_get_attendance_intervals`, iterate over individual records from potentially multi-record `Intervals` payloads to avoid singleton errors. - In `_get_overtimes_to_update_domain` (hr_attendance), localize check_in/check_out to the employee's timezone before computing the date range so overtime lines for dates that only exist in local time are correctly included in the delete-and-recreate cycle. opw-5931665 Forward-Port-Of: odoo/enterprise#111075 Forward-Port-Of: odoo/enterprise#109419
This update fixes an issue where subscription quotations weren't displaying correctly in the portal. Recent changes caused orders to always redirect to a general subscription page, which wasn't suitable for draft or sent orders. Now, draft and sent orders are correctly directed to the specific order details page, improving the user experience.
Original PR description
Version: - saas~19.2 Steps to reproduce: - Create a subscription quotation. - Open it from the portal. Issue: - The portal view of the subscription quotation is not displayed correctly. Cause: - After recent changes, subscription orders were always redirected to `/my/subscriptions/` route. - This route renders the `subscription_portal_template`, which is not suitable when the order is still in draft or sent state. Solution: - If the subscription order is in draft or sent state, redirect the user to `/my/orders/<order_id>` instead. task-5966871
This update fixes an issue where multi-select rectangles on scaled PDF signature pages were inaccurately drawn, leading to selection problems. Additionally, the update resolves a potential error when dropping elements and ensures helper lines align correctly during dragging, improving the overall signature experience. This enhances the reliability and usability of our digital signature process.
Original PR description
When drawing the multi-select rectangle on scaled PDF pages, the rectangle corner was not properly synchronized with the mouse pointer, leading to inaccurate selection. Additional fixes: - An uncaught error could be triggered when dropping elements on the page. - Helper lines during dragging were not accurately aligned around sign items. task-6049004 Forward-Port-Of: odoo/enterprise#111156
This update fixes an issue where repositioning a signature within the PDF viewer caused erratic resizing behavior. The change ensures only one resize listener is attached per signature, resulting in a more reliable and predictable resizing experience for users. This improves the overall quality and usability of the signature functionality.
Original PR description
Previously, repositioning a sign item inside the PDF iframe would attach multiple resize event listeners. This led to inconsistent and unintuitive resizing behavior. This commit ensures that only a single resize listener is registered per item, avoiding duplicated handlers and restoring stable interaction. task-6048759 Forward-Port-Of: odoo/enterprise#111520 Forward-Port-Of: odoo/enterprise#111146
This update fixes an issue where users weren't receiving email notifications for signature requests, even when they preferred to receive notifications in the Odoo inbox. Now, all signature requests will trigger email notifications, ensuring signers are promptly informed. This change maintains in-app visibility for users who rely on the Odoo interface.
Original PR description
When a user's notification preference is set to "inbox", no email is sent, which may prevent signers from being notified of signature requests. This commit enforces sending email notifications for signature requests regardless of user notification settings. Notifications are still created in Odoo, preserving in-app visibility for users who rely on it. task-6041834 Forward-Port-Of: odoo/enterprise#111094
This update corrects a small, unintended message appearing in the documents generated for employee payroll. This ensures that all payroll documents are clear and accurate, providing employees with the correct information. The change is a simple fix to improve document clarity.
Original PR description
Task#5980045 Forward-Port-Of: odoo/enterprise#109063
This update corrects a bug where archived employee versions were incorrectly included in pay run reports. The fix filters out archived employees from the pay run domain, ensuring accurate payroll calculations. This prevents potential errors and ensures data integrity for employee compensation.
Original PR description
Steps to reproduce: 1. Create an employee with a contract for this month 2. Archive the employee (but not the version) 3. Create a pay run 4. The employee's version will appear in the list Cause: The domain takes versions for archived employees. Fix: Add active_employee in the domain. Task: 6022437 Forward-Port-Of: odoo/enterprise#110527 Forward-Port-Of: odoo/enterprise#110073
This update resolves an issue where users were directed to the wrong document form view when configuring PEPPOL document syncing settings. The change adds a dedicated Kanban view for PEPPOL documents within the settings, ensuring users can easily manage their PEPPOL documents. This improves the user experience and streamlines the configuration process.
Original PR description
Before this commit: clicking through on the setting of configuring the folder to sync peppol documents would lead to the document form view instead of the kanban view. Task-6040802 Forward-Port-Of: odoo/enterprise#111765 Forward-Port-Of: odoo/enterprise#111341
This update resolves an issue where documents uploaded to the 'All' folder in the Documents app were inaccessible through the bridge interface. The fix ensures that uploads to 'All' now default to the standard bridge folder, restoring full accessibility for users. This improves the usability of the Documents app.
Original PR description
Problem: When a user uploads a document through a bridge to the Documents app, if the destination is set to the `All` folder, the file becomes unviewable from the bridge. It can only be accessed directly via the Documents app. Cause: This occurs because `All` is not an actual folder. Uploads directed to it default to the `My Drive` folder instead. Because `My Drive` is restricted and inaccessible via the bridge, the uploaded documents remain hidden. Solution: To solve this problem, this PR ensures that uploads directed to the `All` folder default to the default bridge folder rather than to `My Drive`. task-6023290 Forward-Port-Of: odoo/enterprise#111715 Forward-Port-Of: odoo/enterprise#111290
This update resolves a problem where invoice lines were not appearing correctly when certain tax modules (l10n_in and l10n_ar) were installed. The fix ensures that invoice line data is handled properly, preventing conflicts and ensuring accurate display of financial information. This improves the reliability of invoice processing.
Original PR description
Create the invoice line through the `invoice_line_ids` o2m write command instead of a standalone `account.move.line` create with move_id. The mock server's `inverse_fname_by_model_name` mapping only keeps one o2m per co-model; when extra modules add another o2m with the same inverse (`l10n_in_withholding_line_ids` from l10n_in, `l10n_ar_withholding_ids` from l10n_ar_withholding), it shadows `invoice_line_ids` and the list renders empty. runbot-233670 Forward-Port-Of: odoo/odoo#255188
This update ensures the sale dashboard accurately displays orders fulfilled through the POS system. Previously, orders in 'done' status weren't showing up, but this fix now correctly integrates POS order status updates into the dashboard view, providing a more complete picture of sales activity.
Original PR description
Step to reproduce: - install spreadsheet_dashboard_sale and pos_sale - create a order in pos , invoice it too - open sale dashboard Observation: - the order fulfilled in pos, does not reflect in…
Step to reproduce: - install spreadsheet_dashboard_sale and pos_sale - create a order in pos , invoice it too - open sale dashboard Observation: - the order fulfilled in pos, does not reflect in dashboard Cause: - sale has 4 status i.e ["draft", "sent", "sale", "cancel"] - when pos_sale is installed, new status oders are added i.e ['paid', 'invoiced', 'done'] - sale dashboard pivot relies on sale defined status only, which so not consider orders that have status in ['paid', 'invoiced', 'done'] Fix: - fix the domain of pivots such that, it will now accept other orders too **Before:** <img width="1058" height="277" alt="image" src="https://github.com/user-attachments/assets/e58c88fa-5ad3-4194-9f9c-ddf41f2f73de" /> <img width="1116" height="190" alt="image" src="https://github.com/user-attachments/assets/259e0347-5d5b-4d5c-9aeb-74102aa4becd" /> <br/> **After** <br/> <img width="1137" height="232" alt="image" src="https://github.com/user-attachments/assets/406b71a5-1dd8-4164-9d4e-4f0bca34c9e8" /> <img width="1125" height="235" alt="image" src="https://github.com/user-attachments/assets/fded3203-7d72-45ea-b5aa-142ebcd52136" /> opw-5487654 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248142
This update ensures that timesheet entries are correctly removed when a time off request is deleted or cancelled, preventing data inconsistencies. Previously, timesheets lingered even after time off was removed, leading to inaccurate tracking. This fix addresses a bug related to how the system handles time off cancellations and ensures accurate timesheet reporting.
Original PR description
BUG 1: ----------- **Steps to reproduce:** 1. Install Time Off and Timesheets with demo data. 2. Create a time off for an employee and approve it. 3. Check the related timesheet entry for that…
BUG 1: ----------- **Steps to reproduce:** 1. Install Time Off and Timesheets with demo data. 2. Create a time off for an employee and approve it. 3. Check the related timesheet entry for that employee. 4. Delete the approved time off. 5. Check the timesheet entries again. **Issue:** The timesheet entry remains even after the related time off record is deleted. **Cause:** Following commit 944c11e, admins can delete [approved time off ](https://github.com/odoo/odoo/blob/f6cf0d067e5f30e2b22ea513071cd7c5e3d9f44c/addons/hr_holidays/models/hr_leave.py#L956-L959)records. The relationship between the leave and the analytic line (timesheet) did not have a deletion policy defined. When the leave was [unlinked](https://github.com/odoo/odoo/blob/f6cf0d067e5f30e2b22ea513071cd7c5e3d9f44c/addons/hr_holidays/models/hr_leave.py#L961-L964), the analytic line remained without its parent reference. **Solution:** Explicitly remove related timesheet entries before deleting the leave record. BUG 2: ----------- Currently, refusing/cancelling a time off record can lead to orphan timesheets/duplicated hours (16h instead of 8h) if a public holiday exists on the same day. **Root cause:** The issue comes from this write method: https://github.com/odoo/odoo/blob/79ff1d63caed2c1058aa338947b9af90ebb6cd20/addons/project_timesheet_holidays/models/hr_leave.py#L128-L130 The method first unlinks the holiday_id from the timesheets and then attempts to delete them. However, once the holiday_id is set to False, the timesheets are no longer linked to the leave. As a result, leave.timesheet_ids becomes empty, and nothing is deleted. This leads to orphan timesheet records. When the leave is later refused or cancelled, a new public holiday timesheet entry is generated (if applicable), resulting in duplicated timesheet entries for the same day. **Steps to reproduce:** 1. Create a time off for one day and validate it (8h timesheet generated). 2. Create a public holiday for the same day. 3. Observe that leave duration becomes 0, but the timesheet remains. 4. Refuse or cancel the time off. 5. Observe two timesheet entries for the same day (16h total). opw-5384428 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247155
This update resolves a validation error that occurred when creating invoices from POS orders using non-cash payment methods. Previously, enabling cash rounding triggered an error due to a mismatch in how rounding logic was applied. Now, the system correctly avoids rounding when a non-cash payment is used, ensuring invoices are created without errors.
Original PR description
## Issue before this commit: Creating an invoice from a POS order with **Cash Rounding enabled only for cash payment methods** raised an unexpected validation error: > *"The operation cannot be…
## Issue before this commit: Creating an invoice from a POS order with **Cash Rounding enabled only for cash payment methods** raised an unexpected validation error: > *"The operation cannot be completed: Missing required account on accountable line."* This happened when the order was paid using a **non-cash payment method**, but rounding logic was still applied. ## Steps to Reproduce: 1. Install the `point_of_sale` module. 2. Go to POS Configuration → Settings: * Enable **Cash Rounding** * Set a **Rounding Method** * Enable **Only on cash methods** 3. Create a product: * Sale Price: 260 * Tax: 6% 4. Open a POS session. 5. Add the product to an order. 6. Apply a discount (e.g., 1.123). 7. Pay using a **non-cash payment method** (journal not marked as cash). 8. Enable **Invoice** and validate the order *(or create the invoice later from the Orders menu)* ## Cause of the Issue: While `_prepare_invoice_vals` correctly avoids setting `invoice_cash_rounding_id` for non-cash payments, `_create_invoice` still executes rounding logic whenever cash rounding is enabled on the POS configuration. This leads to a mismatch where: * No rounding configuration is set on the invoice * Rounding logic still attempts to create/update rounding lines * Required accounts (profit/loss) cannot be determined * A validation error is raised due to missing account on the generated line ## With This Commit: The rounding logic in `_create_invoice` is now guarded by checking the presence of `invoice_cash_rounding_id`. This ensures rounding is only applied when properly configured and avoids unexpected validation errors for non-cash payment invoices. Steps To Reporduce: [Video Link](https://drive.google.com/file/d/10ticlUW5i5pbu_oDDPqR-jg0hVcNWf3Z/view?usp=sharing) opw-6005320 opw-5951991 opw-6036870 Forward-Port-Of: odoo/odoo#254844
This update fixes an issue where foreign partners were incorrectly identified as being from Argentina due to a technical detail in how identification codes were processed. The change now accurately determines if a partner is in Argentina, ensuring correct business logic and reporting for Argentinean users. This improves data accuracy and reliability.
Original PR description
In `_compute_is_company`, partners were identified as Argentinean (`l10n_ar_partners`) if their identification type had an AFIP code. However, some foreign identification types also carry an AFIP code (e.g., US 'it_fid' uses AFIP code '91'). This caused foreign partners to be incorrectly identified as Argentinean, which led to incorrect `is_company` computation for those records. This change ensures that only partners actually located in Argentina are processed using the local identification heuristic. runbot-241126 Forward-Port-Of: odoo/odoo#252945
This update optimizes how Odoo handles large sale orders, significantly speeding up the rendering process. Previously, calculating parent sections was slow, leading to UI delays. Now, the system pre-computes these relationships, resulting in a much smoother and faster experience when working with complex orders.
Original PR description
This commit resolves a performance bottleneck that occurred when handling very large sale orders (e.g., ~200 order lines). Previously, the util function `getParentSectionRecord` determined the parent…
This commit resolves a performance bottleneck that occurred when handling very large sale orders (e.g., ~200 order lines). Previously, the util function `getParentSectionRecord` determined the parent (sub)section of an order line by iterating over all preceding order lines. Since this logic was executed for each order line, the overall complexity became O(n²). Moreover, this function was invoked inside the `shouldCollapse` method, which is used in multiple UI flows during rendering. As a result, large sale orders could cause noticeable UI slowdowns and block the main JavaScript thread. To address this, we now build a parent–child section mapping once per render in O(n) time. Subsequent lookups simply read from this mapping instead of recomputing the parent by scanning previous lines. This significantly reduces the computational cost and prevents UI blocking when working with large orders, leading to a much smoother rendering experience. opw-5865167 Benchmark: | No. records | Before | After | |----------------|---------------|--------------| | 150 | 1300ms | ~850ms | | Before | After | |---------------|--------------| | <img width="287" height="284" alt="image" src="https://github.com/user-attachments/assets/dd73ab18-3c53-4958-99b7-083dd5cd9e64" /> | <img width="311" height="277" alt="image" src="https://github.com/user-attachments/assets/b6e90fa3-85eb-4d72-b616-28aff9a938e8" />| --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255180 Forward-Port-Of: odoo/odoo#252991
Previously, emails weren't automatically sent when a task was created using a task template. This update ensures that emails are consistently sent, mirroring the behavior when a task is copied. This improves notification reliability for users.
Original PR description
Steps to reproduce: - Open form view project that has task templates. - Add a partner to follow project when task is created. - From `New` button click on any available task templates . Issue: - Mail is not sent when task is created from template. Fix: - Now we are treating creating task from template same as we do copy. Solution: - Make sure we send a mail and stop the normal logging which happens when copying the task. Forward-Port-Of: odoo/odoo#255170 Forward-Port-Of: odoo/odoo#250306
This update fixes an issue where mass email sorting failed due to inconsistent date information in messages. The fix adds a default date of midnight to emails lacking a date or create_date, ensuring reliable sorting and preventing errors during email processing. This improves the reliability of sending emails to applicants.
Original PR description
Background: In odoo.com, due to some migration scripts, there are messages without neither a date nor create_date Issue: When sending mass emails to applicants, when determining the parent email, emails are sorted using their date, but since some emails have a date and some don't, comparing them results in an exception (comparing datetime with bool). Fix: Add datetime.min as a fallback for the email's date if neither date nor create_date are set. Task-6041584 Forward-Port-Of: odoo/odoo#254372
This update resolves an issue preventing invoices sent to partners in Åland Island (AX) from being properly transmitted via Peppol. Previously, invoices were generated and attached but didn't appear in the system chatter. Now, invoices will be sent via Peppol, ensuring seamless integration and enabling companies in Åland Island to utilize Peppol.
Original PR description
Before this commit, invoice to a partner in Åland Island can't be sent via Peppol. XML and PDF are generated, linked to the account.move, but are not sent and don't appear in the chatter. Steps to reproduce: - Create a partner in Åland Island - Create an invoice - Send to Peppol Current behavior: - Invoice is not sent, appear in the attachment, but doesn't appear in the chatter. Expected behavior: - invoice is sent and attachments are in the chatter This also allow activating Peppol for companies in Åland Island. Ticket [link](https://www.odoo.com/odoo/project.task/5949439) opw-5949439 Forward-Port-Of: odoo/odoo#251943
This update resolves an issue where unnecessary data fields (like phone number) were appearing in newly created project tasks when using the contact form. The change ensures that task descriptions only include data that's actually provided, improving the clarity and organization of project information. This was caused by a recent update to how partner data is added to task descriptions.
Original PR description
# How to reproduce - Add a contact form to your website - Make it so the contact form creates a task on submit - Remove some field from the contact form, but no the email (ex: Phone) - Fill in the contact form; the email must be from one of the existing partners - Submit the form and go look at the task in the project application # The problem The fields removed from the form are still present in the task's description (ex: partner_phone: False) # Why This commit (https://github.com/odoo/odoo/commit/7d0660e034f3be1b92869c266dc2cfb0bc6b6941) changed the way the partner's data was added to the description. When adding that data, it does not check if it exists before hand and instead adds a default value if not found. opw-5920816 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252848
This update addresses a customer confusion issue where exporting XML from bills resulted in incorrect customer and supplier information. The 'Export XML' button has been removed for non-imported bills to prevent this problem and ensure accurate data processing. This change simplifies the process for users working with bills.
Original PR description
Problem --------- Currently, in the bills list view, when you select bills > Print > Export XML; not-imported bills gets their customer and supplier party inverted. This is because the XML export of those trigger the XML computation which is not designed for bills but only for invoices or self-bills. For imported bills (coming from Peppols for example), we re-use the imported XML. Since XML export of created bills is not supported anymore. The button leaves customers confused as to why their partner are inverted in the XML. Solution --------- Don't show the "Export XML" if one or more move are selected for the import and don't compute the XML for bills that are not self-bills. 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#255289
This update resolves a bug where the live chat channel name was incorrectly duplicated when a user (agent) was chatting with themselves. The fix ensures the visitor user is handled correctly, preventing this duplication and maintaining accurate channel naming. This improves the overall live chat experience.
Original PR description
Since PR #212150 when getting the livechat channel values, the `visitor_user` value is set to the current visitor user even when the visitor user is the same as the agent (self chat). The code is guarded in the next step and so this visitor is not added to the channel members but the already set value affects the livechat channel name. The bug becomes visible when the `displayName` computation is changed later by the PR #227240. This change ensures that the visitor user remains falsy throughout the process when the visitor and agent are the same. task-6015652 Forward-Port-Of: odoo/odoo#255281 Forward-Port-Of: odoo/odoo#255093
This update ensures that DDT (Documento di Trasporto per il Dazio Dogale) information is displayed correctly for dropship orders in Italy. Previously, this information was missing, creating a discrepancy in reporting. The fix addresses a technical issue related to how the system identifies dropship operations, now ensuring accurate visibility of key shipping documents.
Original PR description
Steps to reproduce the bug: - Create a company with country = Italy and select it - Install the module “l10n_it_stock_ddt” - Activate “Dropshipping” in the inventory settings - Create a delivery → the group "DDT Information" is visible - Create a dropship → the group "DDT Information" is not visible Problem: The DDT information should also be visible for dropship operations. The compute used for “l10n_it_show_print_ddt_button” correctly takes dropship operations into account, but it cannot be reused to control the visibility of the DDT Information group because this compute is True only when the picking state is done and locked: https://github.com/odoo/odoo/blob/e6d4ab62e950c8b88ac54fecbf2682cba846c7c3/addons/l10n_it_stock_ddt/models/stock_picking.py#L34-L35 opw-5190251 Forward-Port-Of: odoo/odoo#254986
This update resolves a bug where invoice cancellations triggered by TicketBAI would block Odoo, leading to data inconsistencies. The fix checks for a security hash before sending invoices to TicketBAI, preventing Odoo from attempting to reset protected invoices. This ensures invoices can be correctly processed and avoids database blocks.
Original PR description
Before this commit, if the user configured the sales journal to be locked by a hash, then a cancellation in ticketbai would 1/ send the cancel request to ticketBAI. This would be processed…
Before this commit, if the user configured the sales journal to be locked by a hash, then a cancellation in ticketbai would 1/ send the cancel request to ticketBAI. This would be processed successfully 2/ try to reset the invoice to draft inside of Odoo, then cancel it. This would fail with an error since account moves protected by a hash cannot be reset to draft. The result is a blocked database where the invoice cannot be altered in Odoo while its status doesn't match the status in ticketBAI. In this commit, we propose to check for the secure hash before sending the invoice over to ticketBAI. The invoice is not altered yet at that stage to account for potential ticketBAI errors in the normal flow. While this option is not great from a usability perspective (preventing secure hashes with ticketBAI is probably best), we believe the current solution offers the best compromise in the context of a bugfix. The issue does not seem to be reproducible outside of production as the core of the problem is a mismatch in state between ticketBAIand Odoo. opw-5912848 Forward-Port-Of: odoo/odoo#250886
This update corrects an issue where product names in the website's table of contents were overflowing when many products were listed. The fix changes the HTML tag used for product titles within the snippet template to ensure it aligns with the table of contents plugin's scanning criteria. This prevents the table of contents from becoming excessively wide and improves the user experience.
Original PR description
# How to reproduce - Have atleast one product published on the website. The more products published, the more noticable the issue is - Edit the website - Add a table block to a page (Search for table…
# How to reproduce
- Have atleast one product published on the website. The more products published, the more noticable the issue is
- Edit the website
- Add a table block to a page (Search for table in the "Insert block" popup and pick the first one)
- Add a catalog block to the table. This catalog block needs to be the one with the title "Our latest content".
- Add any other block in the table block to update the table of content
# The problem
The table of contents display the names of the different products. If there are a lot of products, it fills the whole table of content
# Why
The TableOfContentPlugin scans for ```<h2>``` tags to use them in the table of content.
```js
updateTableOfContentNavbar(tableOfContentMain) {
const tableOfContent = tableOfContentMain.closest(".s_table_of_content");
const tableOfContentNavbar = tableOfContent.querySelector(".s_table_of_content_navbar");
const currentNavbarItems = [...tableOfContentNavbar.children].map((el) => ({
title: el.textContent,
href: el.getAttribute("href"),
}));
if (tableOfContentMain.children.length === 0) {
// Remove the table of content if empty content.
this.dependencies.remove.removeElement(tableOfContent);
return;
}
const targetedElements = "h1, h2";
const currentHeadingItems = [...tableOfContentMain.querySelectorAll(targetedElements)]
.filter((el) => !el.closest(".o_snippet_desktop_invisible"))
.map((el) => ({ title: el.textContent, id: `#${el.id}`, el }));
```
The product snippet template uses ```<h2>``` for their product title dispite having the h6 CSS class.
Note that the reason you need to add another block to the table to see the issue is that the table of content is updated before the products are loaded in the catalog.
opw-5992937
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#253002This update resolves an issue where users without live chat access were encountering an error when trying to open the live chat invite panel. The fix ensures that active live chat partners are correctly retrieved for invited users, improving the usability of the live chat feature. This prevents frustration and ensures a smoother experience for all users.
Original PR description
When opening the livechat invite panel, users without livechat access rights encounter an access error. This commit fixes the issue by ensuring active live chat partners can be retrieved for invited users. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#255207 Forward-Port-Of: odoo/odoo#254565
A bug in the composer was causing a technical error when users selected mentions (@). This was due to an outdated reference to an old attribute name. This update corrects the code to properly handle mentions, ensuring the composer functions smoothly for all users.
Original PR description
Problem: Opening the composer, typing "@" and selecting any item causes a traceback. Cause: After 8c99b17fcc3a612fd897da9ee29e2f53254d5933, the attribute `channel` was renamed to `thread`. Some code still referenced the old `channel` attribute, leading to errors when selecting mentions. Steps to reproduce: - Open the composer. - Type "@" to trigger mentions. - Select any item from the suggestions. - Observe a traceback. opw-6030307 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254127
This update corrects a bug where invoices were displaying the delivery date one day in the past. The fix addresses a timezone mismatch during invoice creation, ensuring the correct delivery date is reflected based on the system's time. This improves data accuracy for sales reporting and customer invoicing.
Original PR description
Currently when the user creates an invoice the delivery date is set incorrectly. <h2>Steps to produce:</h2> * Set system timezone to Asia/Kolkata and time to 5:00 * Install Sales, Inventory * Create…
Currently when the user creates an invoice the delivery date is set incorrectly. <h2>Steps to produce:</h2> * Set system timezone to Asia/Kolkata and time to 5:00 * Install Sales, Inventory * Create and confirm a sale order * Go to Delivery and Validate the delivery * Go back to the Sale order and create an invoice. <h2>Observed Behavior:</h2> The delivery date on the customer invoice is set to one day before the current date, even though the effective date for the delivery correctly reflects the system date and time. <h2>Root cause:</h2> This issue occurs because, when a delivery is validated, the `date_done` field is set using the current time in UTC at [1], because odoo operates in UTC by default. This value is then used to compute the effective date on the sales order at [2], which in turn is used to determine the delivery date on the invoice at [3] and [4]. Users see the effective date on the delivery in their own timezone because `Datetime` fields are converted from UTC to the user’s timezone on the client side as stated in [5]. However problem arises from a type mismatch. The delivery date field is of type `Date`, while the effective date is a `Datetime`. As a result, when the value is assigned at [3] or at [4], only the date portion is passed. Because a Date field does not carry any timezone information, no timezone conversion occurs, leading to the observed discrepancy. [1]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/stock/models/stock_picking.py#L1274 [2]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/sale_order.py#L87-L88 [3]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/account_move.py#L122 [4]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/addons/sale_stock/models/sale_order.py#L301 [5]- https://github.com/odoo/odoo/blob/ebb2b2ef02bbffeac4d11c1acdd7e6b4dc151bf9/odoo/orm/fields_temporal.py#L214-L217 ## **Solution:** Using the `context_timestamp` function makes it possible to work with the `Datetime` in the client’s timezone, which can then be used to correctly assign the delivery date on the invoice. opw-5391189 Forward-Port-Of: odoo/odoo#255404 Forward-Port-Of: odoo/odoo#247122
This update allows users to reverse previously scrapped stock moves, expanding flexibility in inventory management. Previously, this functionality was limited, impacting the ability to correct errors or adjust quantities accurately. This change improves inventory accuracy and streamlines operational workflows.
Original PR description
This commit enables reverting a scrapped move. Previously, it was only possible to revert inventory adjustment moves and commit https://github.com/odoo/odoo/commit/1c7d80a10b5d7db1c4163166bf52b3f3c77044ba was supposed to add the ability in. Task: 6001058
This update resolves an issue preventing the hover effect for Bento product designs within the website editor. The previous version had an incorrect variable reference, which was corrected in this commit. This ensures that users can now properly view and hide product descriptions when hovering over Bento designs.
Original PR description
During the introduction of the Bento product design in commit [1], a specific hover effect to show and hide the description was implemented. However, due to an incorrect reference to the 'catalog' variable, this feature was not available in the editor. This commit updates the variable to the correct one, enabling the feature in the editor. [1]: https://github.com/odoo/odoo/commit/1739b954fa34bc62223d892f2cdacbccebd5f8a2 task-6051497 | Current | This branch | |--------|--------| | <img width="1792" height="836" alt="Capture d’écran 2026-03-19 à 14 29 16" src="https://github.com/user-attachments/assets/7a900d47-73b4-4c35-b51e-8ff847361f0b" /> | <img width="1785" height="901" alt="Capture d’écran 2026-03-19 à 14 16 30" src="https://github.com/user-attachments/assets/eb5312bd-04dd-4acb-a44b-fc500b89ddda" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254886
This update resolves an error that occurred when returning inventory with a zero quantity on the original move. The fix ensures that returns with no quantity are properly valued at zero, preventing calculation errors in inventory valuations. This improves the accuracy of financial reporting.
Original PR description
An error is raised when we try to acces the inventory valuation if a move has been returned and the quantity set on the original move is changed to 0 Steps to reproduce: 1. Install Accounting and…
An error is raised when we try to acces the inventory valuation if a move has been returned and the quantity set on the original move is changed to 0 Steps to reproduce: 1. Install Accounting and Inventory 2. Create a product called "Product" and set the Category to "Goods" 3. Go to Inventory > Configuration > Categories, open category "Goods" and change the costing method to "Average Cost (AVCO)" 4. Go to Inventory > Operations > Deliveries and create a new delivery for any customer with one of product "Product" 5. Validate the delivery, click on "Return" then on "Return All" 6. Validate the return 7. Go back to the original delivery and in Actions, click on "Lock/Unlock" 8. Set the quantity to 0 and save 9. Go to Accounting > Review > Inventory valuation 10. Change the day to any day after today 11. An error is raised Issue: Trying to get the inventory valuation at another day then today will replay the history https://github.com/odoo/odoo/blob/88df50bc96448dfaff28bd37e970ffd18bf8d554/addons/stock_account/models/product.py#L444-L450 Which will call `_get_value()` on the moves related to the product https://github.com/odoo/odoo/blob/88df50bc96448dfaff28bd37e970ffd18bf8d554/addons/stock_account/models/stock_move.py#L388-L391 A ZeroDivisionError will then be raised when trying to get the value of a return move and the original move's quantity is 0 https://github.com/odoo/odoo/blob/873d4d262ed3e85362aa677b5a782d6e7fa00f09/addons/stock_account/models/stock_move.py#L457 Solution: If the original move's quantity is 0, set the value to 0 This ensures the move is valued at 0 if the move has no quantity. In other words, a move that has no quantity shouldn't be considered to have any value as there really is nothing to value. opw-5980600 Forward-Port-Of: odoo/odoo#253392
This update resolves issues with how overtime calculations handle different time zones, specifically preventing crashes and ensuring overtime lines are correctly deleted. The fix ensures accurate overtime intervals are generated and processed, regardless of the employee's location.
Original PR description
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a…
Steps to reproduce (singleton crash): Create an employee in a UTC+ timezone (e.g. Asia/Shanghai or Australia/Adelaide) with an overtime ruleset containing a paid rule. Generate work entries for a period, then create two consecutive midnight-to-midnight attendances in the employee's local timezone. Creating the second attendance crashes with: "ValueError: Expected singleton: hr.attendance.overtime.line(...)". Steps to reproduce (stale overtime lines): With the same setup, delete the attendance after it generated overtime lines. The overtime lines remain in the database instead of being removed. The singleton crash occurred because `end_of_day` in `_get_overtime_intervals` was computed as a naive datetime, implicitly treated as UTC. For UTC+ timezones, the actual local end of day is earlier than UTC midnight. As a result, overtime intervals were computed with a stop time extending past the real local midnight into UTC time. When consecutive attendances were processed together, these extended intervals overlapped. The `Intervals` class (`keep_distinct=True`) merges overlapping intervals into a single entry with a multi-record recordset as payload. The subsequent `overtime.rule_ids.work_entry_type_id` and `overtime.status` calls expected a singleton but received a multi-record set, causing the crash. The same multi-record issue also affected the iteration in `_set_real_overtime_intervals` and the overtime work entry loop in `_get_attendance_intervals`. The stale overtime lines issue occurred because `_get_overtimes_to_update_domain` built its search date range from raw UTC `.date()` values instead of the employee's local timezone. For UTC+ employees whose attendance spans local midnight, the overtime line is dated in the next local calendar day. Since the domain was derived from UTC dates, that next local day fell outside the search range, so the overtime line was never found and deleted when the attendance was removed. Additionally, `_get_localized_times` called `.astimezone()` on naive UTC datetimes without first localizing them, producing incorrect local times for the same reason. Solution: - In `_get_overtimes_to_update_domain`, localize check_in/check_out to the employee's timezone before computing the overtime search date range (with a ±1 day buffer) so overtime lines for dates that only exist in local time are correctly included in the delete-and-recreate cycle. - Fix `_get_localized_times` to call `utc.localize()` on naive UTC datetimes before converting to the employee's timezone. opw-5931665 Forward-Port-Of: odoo/odoo#254543 Forward-Port-Of: odoo/odoo#251812
This update resolves an issue where button colors were inconsistently applied across different themes. Specifically, the contrast-adjusted colors previously used for button outlines were incorrectly applied when users manually selected colors. Now, manual color selections are used directly, ensuring a consistent and visually appealing button experience.
Original PR description
Previously, we created a contrast-adjusted color for the `btn-outline` classes to ensure readability. This was also applied to manual colors selected via Theme tab, which made some inconsistencies…
Previously, we created a contrast-adjusted color for the `btn-outline` classes to ensure readability. This was also applied to manual colors selected via Theme tab, which made some inconsistencies with standard `btn`. This commit fixes that by providing the contrast-adjusted color only on default palettes, and use the manual color as is when selected in the Theme tab. task-5392258 | State | Before | After | |--------|--------|--------| | Normal | <img width="261" height="122" alt="image" src="https://github.com/user-attachments/assets/482ed97f-303c-4332-a748-1130a9ee5db7" /> | <img width="261" height="124" alt="image" src="https://github.com/user-attachments/assets/5e0b14ba-677a-480e-8aad-85c13f3a5f6e" /> | | Hover | <img width="261" height="124" alt="image" src="https://github.com/user-attachments/assets/87cec4fc-521c-4b36-84d3-81460cefa68c" /> | <img width="259" height="123" alt="image" src="https://github.com/user-attachments/assets/b17c309d-2b64-4dc2-a33b-e576831647e0" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#239584
This update ensures that presence status notifications are sent only after a user's presence record is removed from the system. Previously, notifications were sent with outdated information, leading to incorrect status updates. This change guarantees accurate and reliable presence status broadcasts for users.
Original PR description
Before this commit, presence channel notifications for unlinked records were sent before the records were actually removed from the database. This caused `im_status` to be calculated using stale data, occasionally resulting in statuses other than "offline" being broadcast. This commit ensures notifications are sent only after the presences have been unlinked, guaranteeing an accurate status. Forward-Port-Of: odoo/odoo#254186 Forward-Port-Of: odoo/odoo#249314
This update fixes a validation issue related to Saudi Arabia's ZATCA tax reporting. Previously, the system didn't include invoice cash rounding amounts in the payable calculation, leading to validation errors. This change ensures accurate VAT calculations and prevents invoice validation failures.
Original PR description
Currently the generated ZATCA XML is not accounting for invoice cash rounding, leading to an invoice validation issue due to a mismatch in the calculation of PayableAmount. Steps to reproduce: - Have a SA Company setup - Create a [cash rounding] with strategy 'Add invoice line' and rounding 1.00 (UP) - Create an invoice for 99.55 + 15% Tax - Set Cash Rounding Method to [cash rounding] - Confirm and send xml for validation Issue: Validation will issue the following warning `[202] BR-CO-16 : Amount due for payment (BT-115) = Invoice total amount with VAT (BT-112) -Pre-Paid amount (BT-113) + Rounding amount (BT-114).` Analysis: The ZATCA implementation was calculating the payable amount strictly as (TaxInclusiveAmount - PrepaidAmount). This change ensures the rounding amount is fetched and added to the total payable calculation opw-5939550 Forward-Port-Of: odoo/odoo#255178 Forward-Port-Of: odoo/odoo#253555
This update fixes a bug in the website builder where unfolding a group would reset to its default state after a page reload. The change ensures that user-selected group configurations are maintained, improving the website building experience and preventing data loss.
Original PR description
When the user has unfolded a group, then click on an action that reloads the builder, the groups got folded. This commit preserves the unfolded groups, in a similar way as the target was already preserved. Steps to reproduce: - Open website builder on `/shop` - Click on a product card - Unfold the "Products page" group - Click on a reloading action (for example "Floating") - Bug: the unfolded group is folded after the reload task-5973113
This update ensures that analytic lines created from services and materials within sales orders automatically use the 'Project' plan instead of the standard 'Sales Orders' plan. A new setting allows users to customize this behavior if needed, providing greater flexibility in tracking costs. This change improves reporting accuracy for project-based sales.
Original PR description
This change ensures that analytic lines generated from Services and Materials create analytic accounts per Sale Order under the **Project** plan by default, instead of using the dedicated **Sales Orders** plan. A new system parameter `sale.analytic_plan_sale_orders` has been introduced to allow users to override this behavior and define a custom analytic plan for upsell lines when needed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where a "This question requires an answer" alert incorrectly appeared on survey questions, even when it was the first time a user saw them. With recent changes to survey flow handling, we've refined the alert logic to ensure it only displays when a question is part of the post-submit flow and was genuinely skipped by the user. This improves the survey experience for all users.
Original PR description
Purpose ======= Fix the "This question requires an answer" alert which is displayed under the question even if it's the first time the user sees it. Specification ============= Following…
Purpose ======= Fix the "This question requires an answer" alert which is displayed under the question even if it's the first time the user sees it. Specification ============= Following odoo/odoo#215237 conditional questions can now be displayed in the post-submit flow. The purpose was to give the user the chance to see and answer the conditional questions that are triggered by a mandatory question that was skipped. However the condition to display this error alert was only relying on the fact that the question was considered post-submit or not. But now that the post-submit questions also includes the conditional questions that are waiting for answer, this condition is not enough anymore. Making the condition more precise to be sure that the error is displayed only if the questions is considered post-submit AND it's already the post-submit flow or it's the pre-submit flow and the question was effectively skipped by the user. Task-6048598 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254848
This update resolves an issue preventing standard Inventory users from printing inventory count sheets. The fix adjusts access permissions to allow retrieval of system parameters needed for the report, ensuring all users can generate these reports. This improves usability for all inventory staff.
Original PR description
### Steps to reproduce: - Impersonate a user with only Inventory user access rights - Inventory > Operations > Adjustments> Physical Inventory - Select any quant in the list > Print > Count Sheet…
### Steps to reproduce: - Impersonate a user with only Inventory user access rights - Inventory > Operations > Adjustments> Physical Inventory - Select any quant in the list > Print > Count Sheet #### > Access Error: You are not allowed to access 'System Parameter' (ir.config_parameter) records. ### Cause of the issue: The template of the count sheet relies on the `get_param` methods of the `ir.config_parameter` model which requires read access rights on the model: https://github.com/odoo/odoo/blob/69ec92cd6fd1b5f19c3db8763c12f003c9acf0dd/addons/stock/report/report_stockinventory.xml#L36-L39 https://github.com/odoo/odoo/blob/69ec92cd6fd1b5f19c3db8763c12f003c9acf0dd/odoo/addons/base/models/ir_config_parameter.py#L59-L69 This access right is limited to the the `base.group_system` (admin) user group: https://github.com/odoo/odoo/blob/69ec92cd6fd1b5f19c3db8763c12f003c9acf0dd/odoo/addons/base/security/ir.model.access.csv#L118 opw-5959200 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254294 Forward-Port-Of: odoo/odoo#253251
This update resolves an issue where component consumption wasn't accurately tracked in the manufacturing process. Specifically, a technical glitch was resetting the consumed quantity, leading to incorrect inventory levels. This fix ensures components are properly used during production runs.
Original PR description
# Product Configuration *Manufactured Product* - Storable - Tracked by Quantity - Manufacture Route - Has a BOM with atleast 1 component *Component Product* - Storable - Tracked By Lot # How to…
# Product Configuration
*Manufactured Product*
- Storable
- Tracked by Quantity
- Manufacture Route
- Has a BOM with atleast 1 component
*Component Product*
- Storable
- Tracked By Lot
# How to reproduce
- Ensure there is available stock for the component product in a lot
- Create a MO for the Manufatured Product
- Confirm the MO
- Click "Details" on the component product
- Remove the reserved quant and add a new one
- Increase the quantity of this new quant to more than "To Consume"
- Save
- Observe that "Consumed" = The quantity you just set on the quant
- Click on "Produce All"
# The issue
- The Consumed quantity is reset to the "To Consume" quantity.
- Furthermore, a warning popup should be displayed when clicking on "Produce All" but there is none.
- Finally, depending on the version you may get this error message : "You need to supply Lot/Serial Number for products and 'consume' them: - Component Product" even though a lot is already assigned
# Why
All these issues stem from the fact that move_raw_ids.picked from mrp.production is set to False instead of True.
This issue was introduced by this commit (https://github.com/odoo/odoo/commit/ef592464983d66ac76bc71a9886462f1f47dc28d) that changed the way the picked value is set.
In write(self, vals) de stock_move, we have :
```py
if self.env.context.get('force_manual_consumption') and 'quantity' in vals:
moves_to_update = self.filtered(lambda move: move.product_uom_qty != vals['quantity'])
if moves_to_update:
moves_to_update.write({'manual_consumption': True, 'picked': True})
```
Followed a bit later by :
```py
res = super().write(vals)
```
This usually works fine except when vals contains edition commands for move_line_ids. Then, the first write will correclty set picked to True, but then picked will be reevaluted after the second write with :
```py
@api.depends('move_line_ids.picked', 'state')
def _compute_picked(self):
for move in self:
if move.state == 'done' or any(ml.picked for ml in move.move_line_ids):
move.picked = True
else:
move.picked = False
```
If all the resulting move_line_ids from the commands edition have picked set to False, then move.picked will also be set to False.
opw-5937171
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#253607This update resolves an issue where notification reminders failed when attendees had access to companies not visible to the event organizer. The fix ensures that attendee company access is properly checked, preventing access errors and guaranteeing reminders function as expected for all users, regardless of their company affiliations.
Original PR description
[FIX] calendar: use sudo for attendee company access in notifications Invitations with notification reminders fail if the attendee has access to companies hidden from the organizer. ### Reproduction Steps 1. User A (Company 1) invites User B (Company 1 & 2). 2. Add a "Notification" reminder. 3. Saving the event raises an AccessError on res.company. ### Cause When preparing notifications, the attendee's company list is fetched while still in the organizer's environment. The `res.company` record rule restricts visible companies to the organizer's own, so the attendee's extra companies are blocked. Since 9a21edd99e7f, `Many2many.read()` uses `_search()` without `bypass_access`, which explicitly checks read access and raises `AccessError` instead of silently filtering at the SQL level. opw-5916536 Forward-Port-Of: odoo/odoo#253679
This update resolves an issue where creating a project from a template without a linked company would trigger a 'company inconsistencies' error. The fix ensures the customer's company information is correctly applied during project creation, allowing users to seamlessly create projects connected to customers with existing company records. This improves usability and prevents data errors.
Original PR description
### Issue: Creating a project from a template that has no company with a customer who has one results in a "company inconsistencies" error. ### Steps to reproduce: - Install `hr_timesheet` and `project` - Convert a project with no companies and the option "Timesheets" ticked, to a template - Create a new project using the template - In the wizard, input a name and select a customer with a company - Click "Create Project" - An error pops up ### Cause: `hr_timesheet` overrides the `create()` of `project.project` to create an `account.analytic.account` if the project allows timesheet and none is given. During the creation of the analytic account, as the field `partner_id` is `check_company=True`, the error is raised in `_check_company()`. ### Solution: We set the company of the customer on the generated project before building the `analytic_accounts_vals` list. opw-5931994 Forward-Port-Of: odoo/odoo#250150
A bug in Odoo's testing framework was causing it to freeze due to an infinite loop. This has been resolved by switching from an array to a set data structure, which prevents duplicate processing and ensures the testing process completes without errors. This improves the stability of the Odoo system.
Original PR description
Problem: Triggering the `child_of` operator in the testing framework caused an infinite loop that froze Odoo. This occurred because the framework attempted to fetch all children of the root operand without accounting for already visited nodes, resulting in children being added indefinitely. Solution: Switched from using an `array` to `set` to prevent duplicate traversal. Task-6023290 Forward-Port-Of: odoo/odoo#255419 Forward-Port-Of: odoo/odoo#254857
This update corrects an issue where embedded attachments within SDI invoices were overwriting the main XML file, causing import failures. The fix involves storing attachments separately, ensuring data integrity and proper invoice processing. Additionally, the naming convention for attachments has been improved.
Original PR description
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR…
PR #212726 removed a Many2One field and used an existing binary field, `l10n_it_edi_attachment_file`, to store E-invoice files as XMLs. This change was made for security reasons. However, this PR also stores attachments embedded in the `<Allegati>` element of the XML in this same field. This results in three issues when importing invoices from the SDI: 1. The first embedded attachment will overwrite the XML file's contents, corrupting it. 2. Subsequent embedded attachments will continue to overwrite the previous attachment. 3. All embedded attachments are linked to the `account.move` record by the Many2one field `attachment_ids`, which is contrary to the stated goal of PR #212726. These behaviors cannot be replicated in a runbot environment, as there is no way to test the SDI import process in runbot at the time of writing. Localhost environments can replicate this issue by receiving an XML from the test l10n_it API server, or by passing similarly encrypted data to the method `_l10n_it_edi_process_downloads()`. See the method `test_decrypt_invoice_from_IAP()` from PR #250439 for an example of the encryption process. **Solution**: Do not overwrite the field `l10n_it_edi_attachment_file`. Add stored field(s) to master for attachment(s) within an XML's `<<Allegati>` element. This PR also improves how Allegati attachments are named, as my previous PR #246220 could result in files with two extensions (e.g. "filename.txt.TXT"). Ticket [link](https://www.odoo.com/odoo/project.task/5800658) opw-5800658 Forward-Port-Of: odoo/odoo#252806