Tuesday, April 28, 2026
38 changes · saas-19.3
Enhancements to existing features
This update allows customers using the self-order checkout process to modify the selected preset during the ordering stage. Previously, the preset was fixed after selection, leading to potential inconvenience. This change improves the customer experience by providing greater flexibility and control during the self-order process.
Original PR description
Users can now modify the selected preset while completing the self-order checkout flow. Task-5441062
This update enhances the user experience for Odoo's self-order system by allowing splash screens to utilize video backgrounds. This creates a more visually appealing and engaging initial impression for customers, improving brand perception. The change is part of a larger effort to refine the self-order module's user interface.
Original PR description
Allow splash screens in self-order to use video backgrounds for a richer UI experience. Task-5441062
This update aligns the payment process with Bancontact's new branding guidelines. Specifically, the QR code design has been updated to match Bancontact's specifications, and a fix has been implemented to prevent payment requests with a zero amount, resolving a known Bancontact Pay error.
Original PR description
..., point_of_sale, pos_self_order, pos_self_order_bancontact_pay, pos_online_payment --- Following the rebranding of Payconiq to Bancontact, the QR code design has been updated. We now use the frames provided by Bancontact and embed the QR code inside them. Additionally, we prevent sending payment requests with an amount of 0, as Bancontact Pay returns an error in this case. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6000182
This update enhances the Dutch SBR tax reporting process within Odoo by providing clearer status tracking and UI feedback. It streamlines the workflow for users to monitor return submissions, manage errors, and ensures critical actions are blocked until the return is fully accepted, improving data accuracy and user experience.
Original PR description
…workflow This commit integrates the Dutch SBR tax reporting process into the `account.return` workflow to provide better visibility, UI feedback, and tracking for users. Main changes: * Added a new…
…workflow This commit integrates the Dutch SBR tax reporting process into the `account.return` workflow to provide better visibility, UI feedback, and tracking for users. Main changes: * Added a new `l10n_nl_sbr_status` field (Pending, Accepted, Error) to `account.return` to track the submission status for Kanban UI color coding. * Updated the Kanban view to dynamically apply custom CSS classes (`nl-sbr-error`, `nl-sbr-pending`) to the state bubble based on the SBR status. * Introduced an `action_refresh_sbr_status` method and a corresponding "Refresh" button in the Kanban view to manually trigger the status check cron. * Consolidated Chatter messages so that status updates, errors, and submission success notifications log directly on the `account.return` record rather than the closing entry. * Added an `action_reset_tax_return_common` override to prevent resetting or modifying a tax return once it has been accepted by Digipoort. * Modified the UI to hide the "Pay" button unless the SBR return has been fully accepted. * Updated `_on_post_submission_event` to block further processing of the return until the SBR report is accepted. task-6034675 Forward-Port-Of: odoo/enterprise#110516
This update incorporates the latest withholding tax percentages mandated by Ecuadorian regulations (Resolución N.º NAC-DGERCGC26-00000009) for 2026. The changes ensure Odoo accurately calculates and reports these taxes, maintaining compliance with local tax laws. Minor improvements were also made to the English naming conventions for tax records.
Original PR description
Implement the new withholding tax percentages according to "Resolución N.º NAC-DGERCGC26-00000009" for Ecuador, following internal implementation guidelines by TRESCLOUD. SPECIFICATION: - Created the new withholding percentages as new tax records. - Set the previous withholding percentages as inactive to preserve historical data. - Ensured compatibility with existing tax configurations and fiscal mappings. Table with the changes established in "Resolución N.º NAC-DGERCGC26-00000009". <img width="1676" height="303" alt="image" src="https://github.com/user-attachments/assets/79ae91b2-6d31-442f-af3c-74304742c8b6" /> BP: #252917 Forward-Port-Of: odoo/odoo#257513 Forward-Port-Of: odoo/odoo#254018
This update enhances the printing of point-of-sale tickets, specifically addressing issues with coupon codes, point displays, and barcode alignment. It also improves the user experience by ensuring company details are only printed when available and preventing errors in specific regions, ultimately leading to more reliable and accurate order receipts.
Original PR description
In this commit: = - `Next Order Coupon` code below bardcode is displayed. - Displayed correct string for won and balance points. - Logo size increased. - Company details not shown if not available while printing from terminal. - Next order coupon Barcode alignment fixed. - Fixed Lot and Serial number alignment. - Prevented traceback for l10n-specific company (e.g. CL, SE). - Removed extra padding from around "Need an invoice ?" text task-5499545 Forward-Port-Of: odoo/odoo#246520
Resolved issues and error corrections
This update fixes an issue where the BIK (Business Income Key) calculation for company cars wasn't accurately reflecting changes throughout the month. The system now correctly updates the BIK monthly based on the employee's car usage, ensuring accurate payroll calculations and compliance. This impacts the accuracy of employee compensation related to company car usage.
Original PR description
**Description of the issue/feature this PR addresses:** When there is a change of car during a month, the employee will have 2 versions but all will be merged on the same payslips but currently only the BIK of one version is taken into account (or no BIK if the employee has no company car anymore) **Current behavior before PR:** . car_atn value equal the yearly_atn / 12 . ATN.CAR rule returns the car_atn value of the first version **Desired behavior after PR is merged:** . Update the car_atn value to be computed monthly, based on the number of calendar days in the current month . Update ATN.CAR payslip rule, it get the value of the car's atn on the current payslip month then prorated based on the versions periods within the payslip period . Modify the corresponding tests . Add corresponding tests task-6108696 Forward-Port-Of: odoo/enterprise#113484
This update corrects a rounding error that occurred when creating kit products. Previously, the system wasn't properly distributing the cost of components within a kit, leading to inaccurate purchase order values. This fix ensures accurate cost calculations for kit products, resolving potential discrepancies in valuation.
Original PR description
### Steps to reproduce: - Create a kit product with 6 bom lines (with a `cost_share` of `0.0%`) - Create + confirm a purchase order for 1 unit of the kit product at 60 - Validate the delivery #### >…
### Steps to reproduce: - Create a kit product with 6 bom lines (with a `cost_share` of `0.0%`) - Create + confirm a purchase order for 1 unit of the kit product at 60 - Validate the delivery #### > 6 layers were created with values 9.99, 10, 10, 10, 10 and 10 There are two issues with purchased kit valuation addressed in this PR: ### Issue 1: Since 8c199f7783527735b35c9fbda334cbdcd55a004f, the product price unit is not supposed to be rounded anymore. However, kit products rely on the rounded `cost_share` field of the `mrp.bom.line` to determine which part of the price of the kit product is handled by which component: https://github.com/odoo/odoo/blob/591102ff37fef1f0b9a946fee3f9d85789653e65/addons/mrp/models/stock_move.py#L245-L246 https://github.com/odoo/odoo/blob/591102ff37fef1f0b9a946fee3f9d85789653e65/addons/purchase_mrp/models/stock_move.py#L28 https://github.com/odoo/odoo/blob/591102ff37fef1f0b9a946fee3f9d85789653e65/addons/purchase_mrp/models/stock_move.py#L38 This leads to inevitable rounding issues where `60/6` does not match `10`: https://github.com/odoo/odoo/blob/591102ff37fef1f0b9a946fee3f9d85789653e65/addons/purchase_mrp/tests/test_purchase_mrp_flow.py#L1273-L1275 simply because 1/6 is represented as `16.67%` and not by `16.66666666666666%`. However, values such as 1/6 can be obtained if you do not set any `cost_share`, since the kit explosion will equidistribute its cost share: https://github.com/odoo/odoo/blob/591102ff37fef1f0b9a946fee3f9d85789653e65/addons/purchase_mrp/models/mrp_bom.py#L42-L48 ### Fix of this issue: We set the digits to `False` for stability reason as the columns have been initiallised as "numeric" values and needs to stay numeric: https://github.com/odoo/odoo/blob/b007b0a4f7e56f6dc44df3154e13745c9981eae3/odoo/fields.py#L1627-L1650 Note that when the digit is Falsy on the field, the field value is formatted to the second digit by the front end: https://github.com/odoo/odoo/blob/3542c542eac5b204e69a8dd6ae1907cfcef60af3/addons/web/static/src/views/fields/float/float_field.js#L58-L76 https://github.com/odoo/odoo/blob/12e453302a950df4d9ee45954f54bdf610888eda/addons/web/static/src/core/utils/numbers.js#L214-L227 In particular, when we create the bom and set the `cost_share`, all possible values will be rounded to the second decimal just as before. This change will therefore only alter the rounding behavior in the DB for equidistributed values such as `16.66666666666666%`. ### Issue 2: While the value of the kit product is exploded and distributed among components, the values of each individual `stock.valuation.layer` are themselves rounded before creation based on the company currency: https://github.com/odoo/odoo/blob/4188436a9e800b062bf9f3b0055cad86acc47e19/addons/stock_account/models/product.py#L240-L255 https://github.com/odoo/odoo/blob/4188436a9e800b062bf9f3b0055cad86acc47e19/addons/stock_account/models/stock_valuation_layer.py#L30 Now, this is problematic since the sum of the values of the layers is expected to match the total value of the purchase order line (that is, the non-rounded value of the components of the purchased kit). ### Fix of this issue: We compute and distribute the rounding error among layers corresponding to the purchased kit product before creation (since layer values are not expected to be modified afterwards), based on the non-rounded computation, since this value should now be exact (as the unit cost is not rounded anymore). opw-5085457 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#258124 Forward-Port-Of: odoo/odoo#252034
This update resolves an issue preventing AI chat functionality on Safari devices. The fix addresses a compatibility problem with older Safari versions that don't fully support a key streaming technology. By switching to a manual reader loop, the AI chat now works reliably on Safari, ensuring a smooth user experience.
Original PR description
Steps: - Install ai - Open ai chat - Try to send a message - Traceback The AI chat was failing on iOS with a traceback when trying to process the stream response. Even though MDN suggests…
Steps: - Install ai - Open ai chat - Try to send a message - Traceback The AI chat was failing on iOS with a traceback when trying to process the stream response. Even though MDN suggests compatibility, Safari (WebKit) versions prior to 26.4 do not implement the AsyncIterator protocol on ReadableStream. This makes `for await (const chunk of response.body)` throw a TypeError as `[Symbol.asyncIterator]` is undefined. https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream This commit replaces the async iteration with a manual reader loop (`getReader().read()`). This is the low-level primitive supported by all versions of Safari and ensures the stream is properly consumed and unlocked even if the connection is interrupted. Steps to reproduce: 1. Open Discuss/AI Chat on an iPad or iPhone (eg. 26.4). 2. Send a message. 3. The response triggers a JS error. ```js Uncaught Promise > undefined is not a function (near '...chunk of asyncStream...') ``` opw-6054307 Forward-Port-Of: odoo/enterprise#113926
This update resolves an issue preventing portal users from creating tickets via email when automatic assignment is enabled. The fix ensures the system correctly accesses employee calendars across companies, eliminating access errors and restoring ticket creation functionality. This improves the portal's usability for users and streamlines the ticket submission process.
Original PR description
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the…
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the system computes working intervals for users to determine assignment. This computation goes into resource logic, where resource.calendar fields (flexible_hours) are read. If the assigned user is linked to multiple employees across companies, multiple resource.resource records are evaluated. The helpdesk email flow starts in sudo, but the employee calendar lookup explicitly drops sudo before returning the calendar. Then, the calendar is accessed in the portal context, which does not have permission to read the other company's resource.calendar, leading to an AccessError and preventing ticket creation. Although the failure is triggered from Enterprise helpdesk, the actual crash occurs in Odoo (resource.calendar), meaning the fix must be applied there. Fix: Preserve sudo when fetching employee calendars to ensure that scheduling logic does not depend on the access rights of the email sender. A test is added in helpdesk_holidays, as the issue requires both helpdesk (auto-assignment) and hr (employees/resources) to reproduce. The test simulates a portal email flow with a multi-company user linked to multiple employees and ensures ticket creation succeeds. Steps to Reproduce: 1. Install Helpdesk, Employees, and enable multi-company 2. Create two companies (e.g., Company A and Company B) 3. Create one internal user (User X) with access to both companies 4. Create two employees linked to the same user: - Employee 1 in Company A - Employee 2 in Company B Make sure they are set with a start date, but no end date. Needs to be active employee. 5. Create a Helpdesk team in Company A 6. Add Agent X as a team member 7. Enable automatic assignment 8. Configure an email alias for the helpdesk team 9. Create a portal user 10. Send an email from the portal user to the alias Related Ticket: opw-6035099 Forward-Port-Of: odoo/odoo#261156 Forward-Port-Of: odoo/odoo#257720
This update resolves an issue where portal email auto-assignment would fail due to permission problems accessing employee calendars across different companies. The fix ensures the system uses the correct security context when accessing calendar data, allowing ticket creation to proceed smoothly. This improves the reliability of the helpdesk system for portal users.
Original PR description
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the…
Problem: Portal email with auto-assignment crashes ticket creation due to calendar access. When a helpdesk ticket is created via email from a portal user and automatic assignment is enabled, the system computes working intervals for users to determine assignment. This computation goes into resource logic, where resource.calendar fields (flexible_hours) are read. If the assigned user is linked to multiple employees across companies, multiple resource.resource records are evaluated. The helpdesk email flow starts in sudo, but the employee calendar lookup explicitly drops sudo before returning the calendar. Then, the calendar is accessed in the portal context, which does not have permission to read the other company's resource.calendar, leading to an AccessError and preventing ticket creation. Although the failure is triggered from Enterprise helpdesk, the actual crash occurs in Odoo (resource.calendar), meaning the fix must be applied there. Fix: Preserve sudo when fetching employee calendars to ensure that scheduling logic does not depend on the access rights of the email sender. A test is added in helpdesk_holidays, as the issue requires both helpdesk (auto-assignment) and hr (employees/resources) to reproduce. The test simulates a portal email flow with a multi-company user linked to multiple employees and ensures ticket creation succeeds. Steps to Reproduce: 1. Install Helpdesk, Employees, and enable multi-company 2. Create two companies (e.g., Company A and Company B) 3. Create one internal user (User X) with access to both companies 4. Create two employees linked to the same user: - Employee 1 in Company A - Employee 2 in Company B Make sure they are set with a start date, but no end date. Needs to be active employee. 5. Create a Helpdesk team in Company A 6. Add Agent X as a team member 7. Enable automatic assignment 8. Configure an email alias for the helpdesk team 9. Create a portal user 10. Send an email from the portal user to the alias Related Ticket: opw-6035099 Forward-Port-Of: odoo/enterprise#114986 Forward-Port-Of: odoo/enterprise#113047
This update corrects a bug where the Gantt view incorrectly displayed maximum hours for employees with flexible work schedules. The fix ensures accurate hour calculations across all schedules, providing a clearer view of employee time tracking. This improves reporting and scheduling accuracy for flexible employees.
Original PR description
For employees having a `resource_calendar_id` with `flexible_hours`, the max hours displayed in the gantt view were incorrectly `days * hours_per_day`. This fixes it by taking the most relevant data between `days * hours_per_day`, `weeks * hours_per_week`, both, or nothing if the range is more than a month. The new calculation is `(weeks * hours_per_week) + min((days * hours_per_day), (hours_per_week))` task 5075953 Forward-Port-Of: odoo/enterprise#114661 Forward-Port-Of: odoo/enterprise#105266
This update ensures that replacement invoices generated from cancelled invoices accurately display the original invoice's source information (Sales Order reference). Previously, the 'Source' field was missing, hindering traceability. This fix maintains accurate record-keeping and compliance with reporting requirements.
Original PR description
### Issue before this commit: The "Source" (origin) field was missing from the PDF of replacement invoices. While the original invoice correctly displayed the Sales Order reference, the new invoice…
### Issue before this commit: The "Source" (origin) field was missing from the PDF of replacement invoices. While the original invoice correctly displayed the Sales Order reference, the new invoice generated through the request cancel process had an empty origin field. ### Steps to reproduce the issue: 1. Download Sales and l10n_mx 2. Set a UNSPSC Category for one product 3. Go to Sales, create a new Quotation and confirm it 4. Create invoice, confirm and send & print 5. Request cancel button -> create replacement invoice 6. In the new invoice there is no source origin invoice ### Cause of the issue: The invoice_origin field is defined with copy=False. Since the replacement logic uses the copy_data method without explicitly passing the origin value, the field was automatically cleared during the creation of the new invoice. ### Reason to introduce the fix: To ensure document traceability, the fix explicitly passes the invoice_origin from the original invoice to the replacement. This maintains the link to the Sales Order in the database and ensures the "Source" label appears on the printed PDF. opw-6070016 Forward-Port-Of: odoo/enterprise#114099
This update fixes an issue where the 'Configuration' menu was hidden for users with 'All Timesheets' access, preventing them from managing billing targets. The fix ensures that menu visibility updates correctly after changes to billing settings, providing consistent access for all approvers. It addresses a caching problem that caused delays in menu updates.
Original PR description
Steps to reproduce Bug 1: 1. Login as a user with "All Timesheets" (Approver) access. 2. Disable the "Timesheet Assistant" feature for this user. 3. Ensure "Billing Rate Indicators" is enabled in…
Steps to reproduce Bug 1:
1. Login as a user with "All Timesheets" (Approver) access.
2. Disable the "Timesheet Assistant" feature for this user.
3. Ensure "Billing Rate Indicators" is enabled in settings.
Steps to reproduce Bug 2:
1. Login as a user with "All Timesheets" (Approver) access.
2. Disable the "Billing Rate Indicators" setting in company settings.
3. Ensure "Timesheet Assistant" is enabled in settings.
Steps to reproduce Bug 3:
1. Only install 'sale_timesheet_enterprise'.
2. Go to Timesheets > Configuration > Settings.
3. Toggle "Billing Rate Indicators" (timesheet_show_rates) or change the encoding unit (timesheet_encode_uom_id), then save and check the menus.
Issue:
1. The "Configuration" menu is hidden, preventing access to billing targets even if the user has "All Timesheets" access.
2. The "Billing Time Targets" menu is still visible inside Configuration even if the "Billing Rate Indicators" feature is disabled in the settings.
3. Menu visibility does not update immediately after saving the settings. Menus that should appear (e.g., "Employee Billing Time Targets" or "Timesheets Assistant") remain hidden, or vice versa, until the cache is cleared or the server is restarted.
Cause:
1. The `hr_timesheet_enterprise_menu_configuration` was restricted in XML to groups that excluded "All Timesheets" users.
2. The `_load_menus_blacklist` logic in Python only blacklisted billing menus for users who were both Managers and System Admins, leaving them visible to regular Approvers even when the feature was disabled.
3. The load_menus method is decorated with @ormcache and stored in the Registry LRU cache. Menu visibility depends on timesheet_show_rates and timesheet_encode_uom_id through _load_menus_blacklist. When this field is updated, the ORM does not automatically invalidate the cached load_menus result because these specific fields are not part of the configuration fields. As a result, the stale old menu remains in memory.
Fix:
- Updated XML to include `hr_timesheet.group_hr_timesheet_approver` in the Enterprise Configuration menu permissions.
- Refactored `_load_menus_blacklist` to:
- Hide all billing-related menus for all users when the feature is disabled.
- Hide the parent Configuration menu if it would otherwise be empty.
- Override the write method in res.company in both modules and explicitly call env.registry.clear_cache() when the relevant configuration fields are modified.
task-5428010
Forward-Port-Of: odoo/enterprise#106464This update fixes several issues in the SA Electronic Data Interchange (EDI) workflow for invoices. Specifically, buttons were incorrectly displayed for draft invoices, and validation errors weren't consistently shown. The changes ensure that buttons are only visible when appropriate and that validation alerts accurately reflect data requirements, improving the reliability of the EDI process.
Original PR description
Post-merge of the sending refactor, several unintended behaviors were identified in the SA EDI flow: - "Retry", "Process" and "Blocking Invoice" buttons remained visible even when invoice in draft state, which is inconsistent with the expected state flow. - Validations in the send wizard were not triggering uniformly; specifically, the ZATCA Reasons error was not appearing when it should. - Danger validation alerts for the Customer Reference were appearing even when field was correctly filled. This commit addresses these issues by: - Updating the view to hide "Retry", "Process" and "Blocking Invoice" buttons while in the Draft state. - Update validation conditions to show relevant errors in the send wizard and prevent unnecessary danger alerts. task-6149746
A recent update caused crashes when viewing customer previews linked to signed Field Service worksheets. This fix corrects a misapplication of a previous patch that was incorrectly converting signature data. By removing unnecessary base64 encoding, the customer preview now functions correctly.
Original PR description
Steps to reproduce: - 1. Install 'planning_field_service_worksheet'. 2. Open a Field Service planning slot, pick a worksheet template that has a signature property, and sign it. 3. From the slot, open the customer preview (portal page). Issue: - The customer preview crashes with a traceback. Cause: - Commit https://github.com/odoo-dev/enterprise/commit/b6997ed6f9a8fc29233e1d324e91bbda7eae4df2 added .to_base64() on prop['value'] to follow the same pattern as: https://github.com/odoo-dev/odoo/commit/c62d1cec96498f424c42aee87b1428a4615d576c , which fixed real Binary/Image fields that returns BinaryValue objects. That patch was misapplied here. The signature value in this template does not come from a Binary field, it comes from a Properties field, so signature data is already stored as a base64 encoded str. Fix: - Drop the .to_base64() call and embed prop['value'] directly, since it is already a base64 string. task-6157798
This update resolves an issue where the 'is_company' field calculation was not correctly reflecting company status in several Latin American localizations (AR, BR, EC). The change ensures accurate identification of companies, improving the reliability of business processes within these regions. This fix enhances data consistency and functionality for users in these markets.
Original PR description
*: l10n_{ar,br,ec}
In 19.1 we changed the `is_company` field to a computed
stored field.
This change needs to be reflected correctly in many localisations
where the default computed value is too naive.
This commit is introducing a generic fix for most l10n that depends
on the module `l10n_latam_base`.
Improve the test coverage for the computation.
Note: This is not strictly necessary for this fix
on Enterprise side, since we removed the invisibility
condition but in case of some customization relying
on it it's safer if we can deduce it correctly.
Enterprise: https://github.com/odoo/enterprise/pull/114403
Related: https://github.com/odoo/odoo/pull/211043
task-6141307
Forward-Port-Of: odoo/odoo#261414
Forward-Port-Of: odoo/odoo#260224This update resolves an issue where Peruvian identifiers (like driver licenses) were not being displayed correctly in the system. The team removed a restrictive visibility condition on these fields, ensuring they are always visible. This ensures accurate reporting and data capture for Peruvian businesses.
Original PR description
In 19.1 we changed the `is_company` field to a computed stored field. That change broke the visibility for some Peruvian identifiers (driver license, etc). This commit removes the visibility condition on those fields to be displayed all the time. Note: we still add the correct compute on related Community commit for sake of correctness and completeness. Community: https://github.com/odoo/odoo/pull/260224 Related: https://github.com/odoo/odoo/pull/211043 task-6141307 Forward-Port-Of: odoo/enterprise#115204 Forward-Port-Of: odoo/enterprise#114403
This update fixes inaccuracies in how tax amounts are calculated for Argentina (l10n_ar) within Odoo. The changes ensure correct tax calculations by leveraging the core tax engine, improving accuracy and preparing for future adjustments to Argentina's tax regulations. This update is related to a larger effort to ensure accurate tax reporting.
Original PR description
This commit refactors the tax amount calculations on the `_get_vat` and `_l10n_ar_get_amounts` method so that it uses the tax computation engine helpers properly, to prepare for any future fixes done on how Argentina tax calculations differs from all other localizations. This replaces all move line queries with the proper `base_line` calculation, with the proper aggregating methods. related-enterprise-PR: https://github.com/odoo/enterprise/pull/92639 task-4891206 Forward-Port-Of: odoo/odoo#261256 Forward-Port-Of: odoo/odoo#223393
This update fixes inaccuracies in how tax amounts are calculated for Arabic VAT transactions within the Odoo system. By utilizing the system's tax calculation engine, the changes ensure more precise and reliable tax amounts are generated, particularly for sales and invoices. This improves financial reporting accuracy.
Original PR description
- Rewrite all tax amounts calculations on `_get_tributes` and `_get_line_details` to properly use the tax computation engine helpers (`base_line`, and aggregating methods) - Ensure that all final amounts from the calculation are formatted with `float_repr` with appropriate precision. related-community-PR: https://github.com/odoo/odoo/pull/223393 task-4891206 Forward-Port-Of: odoo/enterprise#115069 Forward-Port-Of: odoo/enterprise#92639
This update corrects a problem where the AccountID in Odoo's FAIA XML export was not consistently matching account definitions. This ensures accurate financial reporting for Luxembourg (l10n_lu_reports) by aligning data across key Odoo systems. The fix was part of a larger effort to improve the reliability of FAIA exports.
Original PR description
This is one of several commits fixing the FAIA xml export. The Invoice/Line/AccountID element in SourceDocuments/SalesInvoices and SourceDocuments/PurchaseInvoices must match an account defined in MasterFiles/GeneralLedgerAccounts/Account/AccountID. As the latter uses account_code since PR #65221, the former should too. opw-5427296 [Link](https://www.odoo.com/odoo/unassigned-tasks/5427296) Forward-Port-Of: odoo/enterprise#114254 Forward-Port-Of: odoo/enterprise#113455
This update fixes an issue where group payments were incorrectly processing the full amount of bills with multiple installments. Now, payments accurately reflect the outstanding balance of the first installment of each bill, ensuring correct accounting and payment reconciliation. This improves the accuracy of financial reporting.
Original PR description
Steps to reproduce: 1- Install Accounting and make sure "Batch Payments" is enabled in settings 2- Go to [Accounting -> Vendors -> Bills] 3- Create two bills for the same vendor, ensuring one of them has multiple installments (i.e payment term with 3 installments) 4- Confirm the bills 5- In list view, select both bills and another bill from a different vendor and click on Pay 6- Select "Group Payments" and confirm the payment Description of issue: The batch payment of the first vendor has the full amount for both bills Expected behavior: The payment should consider the full amount of the first bill and the first installment only of the second bill opw-5969972 Forward-Port-Of: odoo/odoo#261371 Forward-Port-Of: odoo/odoo#257871
This update corrects and improves the Sri Lankan accounting integration (l10n_lk) within Odoo. It includes new chart of accounts (CoA) elements, revised tax settings, and adjustments to account mappings to align with Sri Lankan accounting standards. This ensures accurate financial reporting for Sri Lankan businesses using Odoo.
Original PR description
Updates the CoA with new accounts, updated taxes, and adjusted default account mapping to better reflect standard Sri Lankan accounting practice. Enterprise PR: https://github.com/odoo/enterprise/pull/114768 task-6141758 Forward-Port-Of: odoo/odoo#260920
This update fixes an error in how time off is calculated when 'Ignore Public Holidays' is enabled. Previously, the system incorrectly added public holidays to the leave duration, leading to inaccurate 'Approved Time Off' figures. The change ensures that public holidays are excluded from the calculation, aligning with the intended functionality.
Original PR description
# Setup You'll need a User with : - An active contract (for easiness of testing, a contract that started long ago with 8hrs/day) # How to reproduce - Create a new Time Off type with "Ignore Public…
# Setup
You'll need a User with :
- An active contract (for easiness of testing, a contract that started long ago with 8hrs/day)
# How to reproduce
- Create a new Time Off type with "Ignore Public Holidays" enabled
- Create a Public Holiday for Period X
- Create A Time Off request for the User for a Period Y that contains Period X
- Go to the Time Off Ledger
- Remove the Missing Hours filter and search for the dates in Period Y
Exemple of periods :
- Period X => Feb 10 2026 - Feb 10 2026
- Period Y => Feb 9 2026 - Feb 11 2026
# The problem
The "Approved Time Off" and "Difference" values are wrong.
With the given exemples, we'll see Feb 9 and Feb 11 with "Approved Time Off" values of 12hrs, which is wrong since the employee is supposed to work 8hrs a day, so he should have a time off of also 8hrs.
# Cause
The calculation for "Approved Time Off" is the following :
Divide the `number_of_hours` of a hr_leave
By the number of working days during the period of the leave
Using our exemple, we get :
`number_of_hours` = 24hrs
number of working days = 2
Approved Time Off = 24hrs / 2 => 12hrs, but we expect 8hrs
The `number_of_hours` is correct since we checked "Ignore Public Holidays" (which actually means : include the public holidays in the number of hours of a leave)
The problem is that the aggregation for the number of working days excludes automatically
public holidays, without paying attention to the value of "Ignore Public Holidays" :
https://github.com/odoo/odoo/blob/5e623af55fba64e812db6bcaf06d8f7c5d08f055/addons/hr_holidays_attendance/report/hr_leave_attendance_report.py#L193-L202
Explanation for this part of the query : we only keep days where there is no record in
resource_calendar_leaves (`WHERE rcl2.id IS NULL`) that contains that day
and that are considered public (`AND rcl2.resource_id IS NULL`)
# Proposed Solution
We add a `JOIN hr_leave_type` to be able to get the value for
`include_public_holidays_in_duration` ("Ignore Public Holidays").
Then, we make it so we exclude the Public Holidays only if that value is
false (`AND NOT lvt.include_public_holidays_in_duration`)
opw-6082422
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#261259
Forward-Port-Of: odoo/odoo#258963This update resolves an issue where IoT events were missed due to a failure in the longpolling fallback mechanism. Now, if longpolling requests fail, the system automatically switches to using the more reliable WebSocket connection, preventing disruptions like failed Worldline payment confirmations. This ensures consistent event delivery.
Original PR description
Community PR: https://github.com/odoo/odoo/pull/260931 Before this commit, if `onMessage` in `iot_http_service` was called directly, it would fail to fallback to websocket if the longpolling request failed, causing events to be missed. One symptom of this is Worldline payments failing to confirm when using websocket. After this commit, the `_longpolling` method will now throw an error in this case, causing the fallback mechanism to attempt websocket instead. Forward-Port-Of: odoo/enterprise#115143 Forward-Port-Of: odoo/enterprise#114779
This update allows administrators to easily control the automatic resetting of subscription users, providing greater flexibility in managing user accounts. Previously, automated user resets were difficult to override, but this change simplifies the process and offers more control. This improves operational efficiency and reduces potential issues related to user account management.
Original PR description
After this commit, the auto resetting of subscription user is overridable. Doing business logic in CRUD methods makes them impossible to bypass, by encapsulating the logic in another method, it would be easily overridable. Forward-Port-Of: odoo/enterprise#114459 Forward-Port-Of: odoo/enterprise#114055
This update corrects a discrepancy in the system's tests related to new Ecuadorian withholding tax percentages (as defined by a recent government regulation). The changes ensure accurate calculations for purchases and returns, aligning with current tax requirements. This ensures compliance and accurate reporting for our Ecuadorian clients.
Original PR description
In accordance with the implementation of the new withholding tax percentages according to "Resolución N.º NAC-DGERCGC26-00000009" for Ecuador, following internal implementation guidelines by TRESCLOUD. Unit tests are updated to be based on the new withholding percentages. BP #110343 Forward-Port-Of: odoo/enterprise#112957 Forward-Port-Of: odoo/enterprise#110712
This update resolves a bug preventing correct discount allocations when invoices are created with sales in foreign currencies. The fix ensures invoices are balanced accurately, addressing a previous error that caused invoice creation failures. This improves the reliability of our invoicing process for international transactions.
Original PR description
**STEP TO REPRODUCE** 1. Install the sale and accounting module. 2. Create 2 products, and setup each one with a different income account. 3. From the accounting settings, setup an account for Invoice Line discount -> Customer Invoice account. 4. Enable a currency, and create a pricelist for this currency. 5. Create the following SO: pricelist -> the pricelist you created previously. currency rate : 0.000717398539 line a: product_a, price 10, discount 57.85% line b: product_b, price 70, discount 57.85% From this SO, try to create an invoice. It will fail, saying the invoice it tried to create is unbalanced. opw-5974048 Forward-Port-Of: odoo/odoo#257897
This update fixes a bug where bank statement reconciliations could incorrectly link transactions from different companies. The fix ensures that payments and bank statements share the same company hierarchy, preventing foreign tax lines from being added to the wrong company's financial records. This improves the accuracy of financial reporting.
Original PR description
ticket-5992100 When auto-reconciling bank statement lines, the end-to-end UUID lookup correctly checked that matched AMLs and their payment belong to the same company hierarchy, but missed checking that the payment also belongs to the same company hierarchy as the bank statement line itself. This allowed a payment from an unrelated company (sharing the same end-to-end UUID from an inter-company bank transfer) to be matched against another company's bank transaction, pulling foreign tax lines into the wrong company's journal entry. Fix by adding the same parent-path company check between the bank statement line and the payment. Forward-Port-Of: odoo/enterprise#114881 Forward-Port-Of: odoo/enterprise#113279
This update fixes issues with the AI chat interface, primarily addressing readability by reducing header font sizes and correcting formatting errors in AI responses. Specifically, the formatting of bold text within AI-generated content has been resolved, ensuring accurate display of text.
Original PR description
- The font-size of h1/h2 headers is large given the small size of chat channels which makes it harder to read the rest of the text. So, the font-size of h1/h2 headers is reduced in ai chat channels. - This commit removes the double border at the bottom of tables and updates the table borders by using table-bordered bootstrap class instead of border. - This commit also fixes an error where markdown2 2.4.11 doesn't detect the boundaries of bold markup properly causing asterisks to appear randomly inside AI responses. For example, "The **dog**, the **cat** and the **rat**" becomes "The <strong>dog<em>*, the *</em>cat<em>* and the *</em>rat</strong>" where it should only use <strong>dog/cat/rat</strong> task-6109286 Forward-Port-Of: odoo/enterprise#114592
This update resolves an issue where the quick create feature for product variants in the Bill of Materials form was incorrectly creating new, unrelated product templates instead of the intended variants. To ensure correct variant creation, the 'Create' and 'Create and Edit' options have been disabled, requiring users to create variants directly on the product template.
Original PR description
Steps to produce: --- - Install `mrp`. - Go to Manufacturing > Products > Bills of Materials. - Click Create, select a product. - In the Product Variant field, type any value and click "Create".…
Steps to produce: --- - Install `mrp`. - Go to Manufacturing > Products > Bills of Materials. - Click Create, select a product. - In the Product Variant field, type any value and click "Create". Issue: --- Using quick create on the Product Variant field does not create a variant of the selected product template. Instead, it creates a completely new, unrelated `product.template`. This is because the `create()` method on `product.product` is overridden to call super() with context `create_product_product=False`, which suppresses direct variant creation and forces creation through `product.template` instead, see [1]. **Why passing `default_product_tmpl_id` does not help:** One might expect that passing `default_product_tmpl_id` in the field context would cause the newly quick-created `product.product` to be linked to the already-selected `product.template`. However, because of the `create()` override above (introduced in [commit]), the variant creation is always redirected to `product.template`, ignoring any `default_product_tmpl_id` passed in context. It is therefore not possible in any case to quick-create a `product.product` that is correctly and directly linked to the currently selected `product.template`. Fix: --- Disable the "Create" and "Create and Edit" options. Since there is no way to quick-create a `product.product` that is correctly linked to the currently selected `product.template`, the user must create the variant directly on the product template first. [1]https://github.com/odoo/odoo/blob/f04d79d44873d0f1c35303a1a892f3a3a394ea17/addons/product/models/product_product.py#L364-L368 [commit]: https://github.com/odoo/odoo/commit/7389345696720255a9d3c72ca1d9c2f4e4ecd7b8 opw-6127738 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261316 Forward-Port-Of: odoo/odoo#259776
This update ensures that the AI chat window opens in full-screen mode, regardless of how it's initiated – through the system tray or command palette. Previously, the chat would open in a background window, which has now been resolved for a better user experience.
Original PR description
Prior to this commit, when opening the chat with an agent from the systray button, the chat window was opened in the background. This commit fixes the issue by adding a call to `channel.open` which opens the chat when in full-screen mode. This commit also fixes an issue where the chat window wasn't properly opened when done from the command palette. task-5172978 Forward-Port-Of: odoo/enterprise#114840 Forward-Port-Of: odoo/enterprise#114598
This update ensures that when scanning a GS1 barcode on a packaged product, the system correctly incorporates the product's due date. Previously, the system ignored the due date information on the packaging, leading to inaccurate expiration tracking. This change improves inventory management accuracy for products sold in packaged form.
Original PR description
Issue
-----
Scanning a GS1 barcode containing:
- packaging
- lot
- due date
disregards the due date when creating the new lot.
Steps to reproduce
-----
- Enable GS1 nomenclature & packagings
- Create a product
- barcode 23456789012344
- packaging with barcode 01234567890128
- some on hand quantity
- Create a delivery for a full packaging of the product
- Open the delivery in barcode
- Scan 02 01234567890128 15 270101 10 LOT1
- Validate
- Open the lot
> Expiration date is set to today
Cause
-----
The code expects the product be scanned, there is no logic to retrieve it from the packaging when missing.
-----
Ticket:
opw-6073489
Forward-Port-Of: odoo/enterprise#114327
Forward-Port-Of: odoo/enterprise#112490This update fixes an issue where stock wasn't being properly reserved for delivery orders when stock arrived at a child location within the warehouse system. Now, when a delivery order is waiting for stock to arrive at a child location, the system automatically reserves the appropriate quantity, ensuring accurate stock tracking. This prevents over-delivery and improves order fulfillment accuracy.
Original PR description
Steps to reproduce: - Create a storable product with no stock on hand - Create a delivery order from WH/Stock → state is "Waiting for Availability" - Create a receipt with destination WH/Stock/Shelf1 and validate it Problem: The incoming quantity is not reserved against the waiting delivery, even though WH/Stock/Shelf1 is a child of WH/Stock. opw-6124879 Forward-Port-Of: odoo/odoo#261334 Forward-Port-Of: odoo/odoo#261072
This update resolves two issues impacting how users manage manufacturing orders through the Barcode app. Previously, changing the UoM after confirmation or modifying the 'Produce Quantity' would reset, leading to data inconsistencies. This fix ensures that UoM changes are correctly applied and that entered quantity values are preserved, improving data accuracy and usability.
Original PR description
### Issue Two bugs reported in the Barcode app / Manufacturing Order flow: **1. UoM change after confirm leaves MO inconsistent** Changing the UoM on a confirmed MO via the Barcode app does not…
### Issue Two bugs reported in the Barcode app / Manufacturing Order flow: **1. UoM change after confirm leaves MO inconsistent** Changing the UoM on a confirmed MO via the Barcode app does not recalculate `product_qty` / `qty_producing`. The backend locks the UoM after confirm — the Barcode view did not. **2. `qty_producing` reset on wizard open/close** Typing a value in `qty_producing` then opening the "Change Qty to Produce" widget (even closing without saving) caused the typed value to vanish. Root cause: the widget's `onClose` calls `env.model.load()`, which refetches from DB and discards any unsaved form edits. ### Fix - `product_uom_id` in the Barcode MO form is now readonly once `state != 'draft'`, matching the backend. - `openChangeQtyWizard` now saves the record before opening the wizard, so pending edits survive the reload. ### Steps to reproduce **UoM bug** 1. Create an MO, confirm it. 2. Open it in the Barcode app. 3. Try to change the UoM → it was editable (bug). **Qty reset bug** 1. Open a confirmed MO in the Barcode app, go to the header product page. 2. Type a value in `qty_producing` (e.g. `3`). 3. Click the `/ X` button next to it (opens the Change Qty wizard) then close it without clicking "Set Quantity". 4. `qty_producing` reverts to its previous value (bug). ### After the fix - UoM field is greyed out once the MO is confirmed. - Typed value in `qty_producing` is preserved after opening and closing the wizard. opw-5809178 Forward-Port-Of: odoo/enterprise#114452 Forward-Port-Of: odoo/enterprise#114075
This update fixes an issue where stock quantities weren't always correctly reflected in the unit of measure of purchase orders. It now automatically creates pickings for partial and empty orders, ensuring accurate stock tracking. Additionally, the demo stock data was adjusted to prevent negative stock levels, maintaining the integrity of our demo environment.
Original PR description
Make sure that the quantity received is in the unit of measure of the purchase order line. Also, when installing stock, create pickings for partial and empty sale/purchase orders. Finally, since creating we're creating more pickings, we need to raise the demo stock of product_product_12 to not be in negative stock for other modules demo data. task 5431550 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#245281
This update fixes an issue where the ‘Ordered Quantity’ on the delivery slip was incorrectly calculated, leading to inaccurate reporting. Now, the ‘Ordered Quantity’ always matches the actual delivered quantity, ensuring accurate inventory tracking and reporting, especially when no backorders are used.
Original PR description
**Steps to reproduce:** * Install the *Inventory* (`stock`) module. * Create a *Storable Product* and set some *On Hand* quantity. * Go to *Inventory → Operations → Receipts*. * Create a new receipt.…
**Steps to reproduce:**
* Install the *Inventory* (`stock`) module.
* Create a *Storable Product* and set some *On Hand* quantity.
* Go to *Inventory → Operations → Receipts*.
* Create a new receipt.
* Add the product with a *Demand* quantity (e.g. 10).
* Validate the receipt:
* Case 1: Validate with less quantity than demand (e.g. 8) and choose *No Backorder*.
* Case 2: Validate with more quantity than demand (e.g. 12).
* Click on *Print( Delivery Slip)*.
**Observed behavior:**
* The *Ordered Quantity* is equal to the *Delivered Quantity*.
* Case 1 (Demand=10, Done=8):
* Ordered = 8, Delivered = 8.
* Case 2 (Demand=10, Done=12):
* Ordered = 12, Delivered = 12.
**Expected behavior:**
* Case 1 (Demand=10, Done=8):
* Ordered = 10, Delivered = 8.
* Case 2 (Demand=10, Done=12):
* Ordered = 10, Delivered = 12.
**Cause:**
* Clicking on *Print* triggers `stock.action_report_delivery`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/views/stock_picking_views.xml#L156
* This renders `stock.report_deliveryslip`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/report/stock_report_views.xml#L14
* The QWeb template calls `report_delivery_document`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/report/report_deliveryslip.xml#L288-L292
* Which relies on `_get_aggregated_product_quantities`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/report/report_deliveryslip.xml#L157
CASE- 1
* When validating with *less quantity* and *no backorder*:
* In `_get_aggregated_product_quantities`, `qty_ordered` is initialized to `None` and only set when `backorders and not kwargs.get('strict')`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move_line.py#L881
* If no backorder exists, the condition fails and `qty_ordered` remains `None` and it come out of condition
* where it take quantity `'qty_ordered': qty_ordered or quantity,` https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move_line.py#L898
* As a result, *Ordered Quantity* becomes equal to *Delivered Quantity*.
CASE-2
* When validating with *more quantity* than demanded:
* `_action_done` creates an extra move using `_create_extra_move()`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move.py#L1936
* The extra move is merged back via `_action_confirm(merge_into=self)`: https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move.py#L1878
* The original move keeps `product_uom_qty = 10` but now has two move lines (10 + 2).
* In `_get_aggregated_product_quantities`: Both move lines share the same `line_key`
- **ML1** → `line_key` not yet in dict → enters [if] https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move_line.py#L880 **ML2** → `line_key` already in dict → enters `else` block https://github.com/odoo/odoo/blob/5c1000cb11da64bf317f9bd9b0ae71f6fbea910d/addons/stock/models/stock_move_line.py#L901-L903
→ `qty_ordered += 2` → `qty_ordered = 12` ✗ (surplus added to demand)
→ `quantity += 2` → `quantity = 12` ✓
* The `else` branch was designed to aggregate multiple lines of the
same product (e.g. two lot lines). The bug was that it added the
**done qty** of each line to `qty_ordered` unconditionally, causing
the surplus from over-delivery to inflate the ordered quantity.
* After the fix:
* Case 1 (Demand=10, Done=8):
* Ordered = 10, Delivered = 8.
* Case 2 (Demand=10, Done=12):
* Ordered = 10, Delivered = 12.
* NOTE:
Adapt the existing test case `test_kit_packaging_delivery_slip`
to reflect the corrected behavior of delivery validation.
The test was originally introduced in this [commit](https://github.com/odoo/odoo/pull/161920/changes/47da1ec13a2189e826d3b0539e6494e35990ccc1).
Its main objective is to ensure that the Delivery Slip report prints successfully
Previously, when validating a transfer with:
Delivered quantity less than the demanded quantity, No backorder created
the Ordered Quantity was being reduced(24->12) to the delivered quantity.
After the fix, the Ordered Quantity correctly remains equal(24->24) to the original demand.
<details>
<summary>Click here to see the results:</summary>
<p><strong>Before:</strong></p>
<div>
<img src="https://github.com/user-attachments/assets/88d24079-b278-4ef9-bff2-c7f14fe7ecb7" />
<img src="https://github.com/user-attachments/assets/c6181771-7d91-4ffe-9ed8-17dffac346f7" />
</div>
<p><strong>After:</strong></p>
<div>
<img src="https://github.com/user-attachments/assets/6ed57881-8af3-42ad-94d4-7c44a5b9b00e" />
<img src="https://github.com/user-attachments/assets/b5506c81-3ed9-416b-8099-108a75588b13" />
</div>
</details>
---
opw-5874759
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#261612
Forward-Port-Of: odoo/odoo#250587This update resolves an issue where expense card payments were incorrectly rejecting transactions from airlines, car rentals, and hotels due to missing Merchant Category Codes (MCCs). The update adds the necessary MCC ranges to the system, ensuring these expense types can be processed correctly. This improves the functionality of the Stripe expense card.
Original PR description
In the expense card, when a payment is made. The card can be filtered to only allow certains category of merchant. However, the 3 ranges of MCC we not added: - Airlines, air carriers: MCC's from 3000 to 3350 - Car Rental Agencies: MCC's from 3351 to 3500 - Lodging, hotels, motels and resorts: MCC's from 3501 to 3999 And since the MCC are not present in the list, they are rejected by default even the card is set to accept all MCCs. task-5486945 Forward-Port-Of: odoo/enterprise#115379 Forward-Port-Of: odoo/enterprise#114154