Thursday, March 5, 2026
22 changes · saas-19.2
New functionality added to Odoo
This update introduces the ability to integrate with popular food delivery platforms like GrabFood and GoFood directly within our point-of-sale system. This allows restaurants to seamlessly manage orders from these platforms, streamlining their operations and improving customer experience.
Original PR description
Introduction: This commit integrate with multiple platform order platform in SEA. This commit also implement a skeleton code base for future adding additional platform order provider. As of now, we included GoFood and GrabFood to begin with. Features list: - Skeleton code for platform order - GrabFood integration - GoFood integration task-4215826 task-3726824 Forward-Port-Of: odoo/enterprise#94390
Enhancements to existing features
This update refines how stock push rules are triggered within Odoo. Previously, rules were based on the move and destination location. Now, rules are determined by the individual move lines and their destination locations, leading to more accurate and efficient stock transfers. This change enhances the reliability of automated stock management.
Original PR description
This PR changes how push rules work. Instead of making push rules work on the move and the move destination location, they now work on the move_lines and the move_lines destination location. Task-5212472
Resolved issues and error corrections
This update fixes an issue in the batch transfer report where product lines were scattered, making it difficult for operators to quickly locate items. The report now sorts move lines by product, grouping similar products together for faster and more accurate picking, reducing wasted time and potential errors.
Original PR description
Issue Before This Commit: ======================= In the `batch transfer report`, move lines are ordered by the `picking's batch sequence` (picking_id.batch_sequence). When operators use the document…
This update ensures invoices sent to French, German, or Belgian customers comply with the latest regulations for Factur-X and ZUGFeRD formats. It also adapts invoice formats for B2B and B2G transactions in Germany, using ZUGFeRD for business-to-business and XRechnung for business-to-government invoices, improving clarity and accuracy.
Original PR description
Updating the FacturX format (France)/ ZUGFeRD format (Germany) to respect the new norms: Factur-X 1.07.3 EXTENDED and ZUGFeRD 2.3.3 EXTENDED. Add the differentiation between these two formats in the customer interface, even if they point to the same value in the code. It clarifies things for the customer, things are called by their name. Also, in Germany, for B2B invoices (peppol EAS = 9930), use ZUGFeRD, but for B2G invoices (peppol EAS = 0204), use XRechnung. Adaptation of the default values in the partner form according to this statement. For French and German companies that are sending invoices to French, German or Belgian customers, changed the default format of invoice sent to be compliant to PDF/A-3 norms. task-5266286 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252018 Forward-Port-Of: odoo/odoo#237091
This update speeds up testing for the Stock Barcode module by optimizing the initial setup process. Specifically, the creation of a company, which was a significant bottleneck, has been moved to a setup class. While fully moving all setup to the setup class initially caused test failures, this change represents a key improvement in test execution time.
Original PR description
TestBarcodeClientAction [setup is quite slow](https://runbot229.odoo.com/runbot/static/build/102958171-master/tests/profile/profile_2.html#localProfilePath=1), especially because it creates a company. In addition in all classes extending this one, we spend at least 6 minutes on this line. (when testing sale_timesheet -> !stock_barcode_mrp_subcontracting) This commit proposes to move at least the company creation in a setupclass. It would be great to move all the setup in the setupclass but the tests are failling when doing so and could be achieved by a member of the stock_barcode owner team. Tests based on this setup should be a few minutes faster with this change. Forward-Port-Of: odoo/enterprise#109509
Issue Before This Commit: ======================= In the `batch transfer report`, move lines are ordered by the `picking's batch sequence` (picking_id.batch_sequence). When operators use the document to pick items, they have to scan through the report to find all lines for the same product. As a result, operators `lose time scanning the document` and `risk of missing lines`. Steps to Reproduce: ======================= - Install the `stock_picking_batch` module. - Create `multiple deliveries` with several `common products`. - Add these deliveries to a batch transfer and print the batch transfer report. - Observe that product lines are ordered by location and then by picking. Cause of the issue: ======================= The batch transfer report currently sorts move lines by picking in the report `(picking_id.batch_sequence)`. When the same product exists in another picking, This causes lines for the same product to be scattered across the report instead of being grouped together, causing the product to appear in multiple places in the document. After This Commit: ======================= In the report, move line sorting by picking (picking_id.batch_sequence) has been replaced with sorting by product `(product_id.id)`. Move lines are now ordered by product, so similar products are displayed together in the document. This helps operators find products more quickly, reduces scanning effort, and makes the process more reliable. TaskID-5379367 Forward-Port-Of: odoo/odoo#241809
This update fixes an issue where manually created stock transfers without references were incorrectly merging into existing transfers. The change ensures each manual transfer creates its own distinct operation, preventing data inconsistencies and improving the accuracy of multi-step stock workflows. This improves the reliability of inventory management.
Original PR description
*: purchase_stock Issue Before This Commit: ====================== In a `multi-step` configuration, while validating a transfer that has no `stock reference`, its next operation (Input → QC → Stock)…
*: purchase_stock
Issue Before This Commit:
======================
In a `multi-step` configuration, while validating a transfer that has no `stock reference`, its next operation (Input → QC → Stock) is merged into an existing transfer that also lacks a stock reference, even when the transfers are manually
created and not generated from a Sales or Purchase Order. This results in unrelated transfers being grouped together.
Steps to Reproduce:
======================
- Install the `stock` module.
- Configure the warehouse to use `three-step reception`.
- Create and validate two receipts for Product A (qty 10) with Vendor A.
- `Observation`: the next transfers for both receipts are merged into a single transfer, even though both receipts were
created manually and not generated from any same source document like PO/SO.
Cause of the Issue:
======================
In the `_search_picking_for_assignation()` method, when no `stock.reference`is defined on a move, the system still attempts to find an existing picking using the `partner_id`. Additionally, in the `_key_assign_picking()` method, moves
without a `reference_ids` are grouped based on their `partner_id`. As a result, validating multiple manually created receipts sharing the `same vendor` causes them to be incorrectly merged into the `same next transfer`, since they do not share a common stock reference.
After this Commit:
======================
The `_search_picking_for_assignation()` method now skips searching for existing pickings when moves lack a `stock.reference`. The `_key_assign_picking()` method groups moves by their `originating picking` instead of the partner, preventing merges between unrelated transfers without a stock reference. This ensures each manual transfer creates its `own next operation` in multi-step routes.
Task-ID: 5242340
Forward-Port-Of: odoo/odoo#251827
Forward-Port-Of: odoo/odoo#235423This update corrects an issue where the display of shift durations in the Planning app was inaccurate when shifts spanned across multiple days. Specifically, the system incorrectly truncated shift names when the duration was less than 3 hours. The fix removes outdated logic related to snapping to the grid, ensuring accurate shift duration display across all durations.
Original PR description
### Issue: The pill name contains the hours when it spans over the next day for less than 3 hours but not if more than 3 hours. ### Steps to reproduce: - Go to Planning app - Create a shift for an…
### Issue: The pill name contains the hours when it spans over the next day for less than 3 hours but not if more than 3 hours. ### Steps to reproduce: - Go to Planning app - Create a shift for an employee from 3pm to 2am (over two days) - The hours of the shift are displayed - Modify the shift end to 3am - The hours of the shift aren't displayed ### Cause: Before the refactor adapting the gantt view to OWL, when a shift spanned over two days less than three hours, then the gantt view truncated the pill to display it in only one day. (see [`_snapToGrid()`](https://github.com/odoo/enterprise/blame/a16b2ef569903c0ae5803c169dbd68acd0141fe1/web_gantt/static/src/js/gantt_row.js#L1044-L1072)) The same logic was done for the computation of the pill's name in [this commit](https://github.com/odoo/enterprise/commit/98a86cbacf484646f486e4648788cfa53cc9648c). But as the pills are no longer truncated since 17.0, the computation of pill names is faulty. ### Solution: We remove the checks of the 3-hour margin. This also makes the variable `spanMoreThanOneDay` useless, so we delete it. opw-5881532 Forward-Port-Of: odoo/enterprise#109397 Forward-Port-Of: odoo/enterprise#107233
This update resolves an issue preventing the export of Eco-Voucher reports from the Belgian payroll module. The change addresses a technical update related to versioning changes, specifically removing a deprecated 'state' field and aligning it with the new version module. This ensures accurate Eco-Voucher reporting for Belgian companies.
Original PR description
Since the switch from contracts to versions, exporting Eco-Vouchers to excel has not been functional, this commit fixes this. **Steps to reproduce:** - Open Payroll App as a Belgian company - Under Reporting Menu, select Eco-Vouchers - Try exporting with XLSX **Issue:** Since introduction of versions, version module does not contain state field anymore which was present in contracts **Fix:** Removed the state field and replaced it with the corresponding field in version. task:5163668 Forward-Port-Of: odoo/enterprise#109500 Forward-Port-Of: odoo/enterprise#97375
This update corrects a bug related to invoicing in Saudi Arabia. Previously, invoices created with a date and time in SA could be incorrectly set to a future date, leading to rejection by ZATCA. This fix ensures invoices are always created with a valid date and time, respecting Saudi Arabian time zones.
Original PR description
In odoo/odoo#236865 we decided to allow clients to backdate invoices by letting them use the `invoice_date` field for the invoice date and use the current time as the issue time because we are not supposed to use a dummy value for time. This created an issue where if a user in a timezone before SA tries to invoice a document around midnight using the current date in SA the datetime created will be in the future which will lead to the invoice being rejected by ZATCA. This commit makes sure we normalize the selected date wrt to the current datetime in saudi arabia so that we never accidentally invoice into the future. task-5890423 opw-5373067 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#250999 Forward-Port-Of: odoo/odoo#246311
This update resolves an issue where sales staff couldn't change or reset payment tokens in subscriptions due to an access error. A recent change in how Odoo calculates payment token display names triggered this error. This fix ensures that the display name for payment tokens is correctly computed, allowing users to manage their payment information as intended.
Original PR description
Use case: - install `payment_sepa_direct_debit` module. - As salesman go to a subscription and try to change/reset the payment token field. When trying to get the values of the `payment_token_id` fields [`name_search()` call] an `AccessError` is raised saying that we don't have access to `payment.provider` model. Since odoo/odoo@a3eef91230e0, fetch() do compute fields, so for payment token this means that `display_name` will be computed without su=True flag, thus it may raise an `AccessError` if accessing some payment provider fields. So this commit force building token display name as sudo, to ensure it can be correctly computed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251996
This update fixes an issue where taxes weren't correctly applied when the tax's fiscal position was set to 'all'. The change ensures that taxes with this setting are now applied appropriately, aligning with expected behavior. This resolves a discrepancy between the sales order's fiscal position and the actual tax application.
Original PR description
### Issue: No tax will be applied if in taxes, fiscal position is set to all. #### Steps to reproduce: 1- Create a tax, and in the tax form, leave `Fiscal Position` field blank, which in this case…
### Issue: No tax will be applied if in taxes, fiscal position is set to all. #### Steps to reproduce: 1- Create a tax, and in the tax form, leave `Fiscal Position` field blank, which in this case `all` will be shown in placeholder. 2- Set Domestic FP to be applied automatically, and set the country to `US`. 3- Create a Partner with `US` country_id. 4- Create a product, and apply the created tax to sale taxes. 5- Create a SO with created partner and the created product. 6- As you see, the tax is not applied to the line, while if you check SO's fiscal position, it is set to Domestic. Expected: As tax's fp is set to all, we expect this tax being applied with Domestic fp. ### Cause: In this line, if no `tax_ids` is set, it means fp has not tax_ids: https://github.com/odoo/odoo/blob/0c3ae7f78d313885984c99a4e57485d9660dd974/addons/account/models/partner.py#L154-L158 However, this might also mean the tax has no fp because `fp.tax_ids` is a Many2Many relation. In the forms, `tax.fiscal_position_ids` being empty is shown as `all` in the placeholder, which means when no tax applied to fp, we expect all taxes to be mapped. ### Fix: This can be fixed by making sure the fp.tax_ids is not empty because there is no `tax.fiscal_position_ids` set. ### Remark: In this fix we rename `TestInvoiceTaxes._create_invoice` to `_create_invoice_taxes_per_line` to avoid override of `AccountTestInvoicingCommon._create_invoice`. This is already done on saas-19.1+. opw-5463245 Forward-Port-Of: odoo/odoo#251872 Forward-Port-Of: odoo/odoo#244155
This update fixes an issue where the price per unit was incorrectly displayed in the shopping cart when products were purchased with packaging. The fix ensures that the price per unit accurately reflects the product's price divided by the actual quantity purchased, resolving a discrepancy in the displayed cart totals. This improves the accuracy of pricing information for customers.
Original PR description
Issue: --- Due to this issue, price per unit is not shown correctly in case of packaging. Steps to reproduce: --- 1- Create a product. Set price: 2.6 per kg. Set `Base Unit Count` to 1. 2- Create a…
Issue: --- Due to this issue, price per unit is not shown correctly in case of packaging. Steps to reproduce: --- 1- Create a product. Set price: 2.6 per kg. Set `Base Unit Count` to 1. 2- Create a packaging of 0.5 kg, and add it to product in Sale tab. 3- Navigate to the shop and add 0.5 kg of the product to cart. 4- Navigate to the cart. Expected: The line price/unit should be 2.60/kg. Current outcome: It's shown 1.30/kg. Cause: --- Currently `_get_base_unit_price(product_price/line.product_uom_qty)` is shown to user as price/unit. `product_price` is calculated using `_get_cart_display_price()` which returns each line's `subtotal` or `total`. In our case, it will be `_get_base_unit_price(1.30/1)`, having base_unit_count set to 1, we will have 1.30 which is wrong. Fix: --- We would need to divide the line price by `product_qty` instead of `product_uom_qty`. Then in our example we would have: `_get_base_unit_price(1.30/0.5) = 2.60`. opw-5973097 Forward-Port-Of: odoo/odoo#251860 Forward-Port-Of: odoo/odoo#251501
This update optimizes the ZATCA onboarding process for journals by reducing memory usage. Previously, a lengthy check looped through all journal entries, causing errors with large volumes of data. Now, the system directly searches for relevant documents, significantly improving performance and stability.
Original PR description
Behavior before: Sanity check looped over all account moves of the journal, filtering in Python for ZATCA documents. This caused memory errors when the journal had hundreds of thousands of moves. Behavior after: The check now searches directly on l10n_sa.edi.document with a domain that filters only relevant moves with state 'to_send', reducing memory usage and avoiding Python-level loops. Root cause: Loading all moves and their One2many edi_document_ids in memory for filtering caused excessive memory usage and MemoryError on large journals. OPW-5972073 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251732
This update corrects a recent issue in the l10n_ch_hr_payroll module by reintroducing the calculation of contractual annual wages. This ensures accurate payroll processing for Swiss businesses using this module, aligning with local tax regulations and improving financial reporting.
Original PR description
Forward-Port-Of: odoo/enterprise#109264 Forward-Port-Of: odoo/enterprise#109228
This update optimizes Odoo's database queries by preventing unnecessary SQL generation, particularly for complex field relationships. Specifically, the system now avoids generating slow SQL when accessing related fields like email content, improving overall performance and reducing resource consumption. Additionally, certain models with intensive access checks have been optimized for faster processing.
Original PR description
## [FIX] orm: stop generating slow SQL Update the context variable to cover the case where we have a related field such as "mail_message_id.body" which is not ran un sudo. In that case, we don't want to generate the SQL. ## [FIX] orm: _access_domain_heavy Mark some models that have heavy access checks so that they can be handled in a special way for performance reasons. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249283
This update resolves an issue where filtering by 'Analytic Distribution' (set/not set) in journal entries and purchase orders produced incorrect results or errors. The fix ensures accurate filtering by correctly handling boolean values related to analytic distribution accounts, improving data accuracy and reporting.
Original PR description
**Problem:**
When filtering by "Analytic Distribution" in views, using "is set" or "is not set" filters (or searching for False) causes a "search domain not valid" error or returns incorrect results.
**Steps to reproduce:**
1) Go to Accounting > Journal Entries.
2) Apply a filter for Invoice lines > Distribution Analytic Account.
3) Select "is set" or "is not set".
4) Check records.
Issue produces error "search domain not valid". Also reproduceable on Purchase Orders.
**Cause:**
The `_condition_to_sql` method did not handle the `('=', '!=')` operators early enough, so it always went to the "operation not supported" error.
**Solution:**
- We need to move the handling of the operators '=', '!=' early enough in the `_condition_to_sql` method.
opw-5478688
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#251816
Forward-Port-Of: odoo/odoo#247777This update fixes an issue where combo product refunds weren't correctly handling orderlines with quantities exceeding the combo's total. Now, the system accurately refunds the full quantity of each item within a combo, regardless of individual orderline amounts. This ensures accurate refunds for complex combo orders, improving the user experience.
Original PR description
When refunding a combo item, the 'To Refund' text would always show the same quantity for all the orerlines as for the combo. But combos could have orderlines with a higher quantity than the combo itself (i.e. 3 menus with 2 burgers each - 6 burgers in total. Now the POS would only let us refund up to the limit qty of the combo, so 3 instead of all 6 burgers) After the fix, we check the quantity of each line in the combo and we refund the full quantity (i.e. if you have a 3 menus with 2 burgers each - 6 burgers in total. The burgers will be divided per combo, so each menu refund will automatically refund 2 burgers.) Task-[5503962](https://www.odoo.com/odoo/project/1737/tasks/5503962) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248212 Forward-Port-Of: odoo/odoo#244702
This update optimizes the HTML editor's performance by reducing unnecessary layout recalculations. Specifically, the code now prioritizes reading the layout before making changes to the DOM, leading to a smoother and faster user experience. Additionally, frequent updates are now controlled to prevent performance issues.
Original PR description
Description of the issue this PR addresses: I. The power buttons positioning logic was interleaving DOM writes and layout reads during selectionchange, causing repeated style/layout recalculations.…
Description of the issue this PR addresses: I. The power buttons positioning logic was interleaving DOM writes and layout reads during selectionchange, causing repeated style/layout recalculations. This PR reorders the logic so geometry is read first and DOM mutations are applied afterwards, reducing the number of forced reflows and significantly improving performance. II. Debounce `updateHints` and `updatePowerButtons` to avoid excessive UI updates on frequent selection changes. Introduce `debounceHints` and `debouncePowerButtons` editor config options so debouncing can be disabled in tests for deterministic behavior. III. Introduce READ helper for withSequence to explicitly order resource handlers so DOM reads run before DOM mutations. Before: <img width="1705" height="399" alt="image" src="https://github.com/user-attachments/assets/2fca797a-0311-4c4a-9063-2051934baa7c" /> After: <img width="1490" height="343" alt="image" src="https://github.com/user-attachments/assets/0f295969-b962-4190-a7f9-fe5366d7fafd" /> task-5499625 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252001 Forward-Port-Of: odoo/odoo#244478
This update fixes an issue where analytic asset depreciation reports weren't accurately distributing amounts when the analytic filter was enabled. The change ensures that depreciation calculations now correctly reflect the distribution of amounts across the relevant analytic accounts, improving the accuracy of financial reporting.
Original PR description
Previously, when the analytic filter is enabled in the depreciation schedule, the total depreciation amount was shown in each respective depreciation column, and the analytic distribution was not taken into account. This commit fixes the depreciation amount for assets with analytic distribution in the depreciation schedule report. When the analytic filter is enabled, the amounts are computed correctly under each analytic's depreciation column. task-5959962 Forward-Port-Of: odoo/enterprise#108484
A recent update caused a disruption in our SEPA direct debit payment processing. Customers were unable to complete payments using this method due to a technical error. This fix resolves the issue by correcting a missing data element, restoring functionality for SEPA direct debit payments.
Original PR description
Issue: --- The SEPA direct debit is broken. Steps to reproduce: --- 1- Enable SEPA direct debit in payment providers. 2- Add something to cart and try paying using SEPA direct debit. You get the error: `payment.provider object has no attribute company.` Cause: --- This is introduced after #250326. opw-5993720 Forward-Port-Of: odoo/enterprise#109672
This update fixes an issue where flexible resources were incorrectly displaying a total of 40 hours per week. The fix ensures that the resource's individual schedule (e.g., 38 hours) is accurately reflected when calculating available hours. This improves the accuracy of scheduling and resource allocation.
Original PR description
### Steps to reproduce: - Download Planning app - From the employees app, create an employee - Assign that employee a new schedule that is 'Flexible', has 07:36 hours/day 'Avg', and has 'Total' 38 hours/week - Search for that employee in the planning app and hover over their name ### Cause of Issue: The total available hours for that employee show as 40h. This is because when calculating the hours per week for the resource, the resource's schedule is not taken into account but the company's. ### Fix: Add the hours per week for the resource's calendar (if available) in the calculation opw-5954982 Forward-Port-Of: odoo/odoo#250185
This update fixes an issue where the time was not accurately displayed in direct message conversations. The change updates how the system retrieves time zone information, ensuring correct time formatting is used for all direct messages. This improves the user experience by providing accurate time information.
Original PR description
Before this PR: The time was not displayed in direct message conversations because the timezone dependency relied on `thread.correspondent`, while the correspondent is now stored on the `channel` model since https://github.com/odoo/odoo/pull/241072. After this PR: The timezone dependency now retrieves the correspondent from `thread.channel.correspondent`, ensuring the correct timezone is used and the time is displayed properly in direct messages. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr