Tuesday, February 24, 2026
14 changes · saas-18.3
Enhancements to existing features
This update adds tests to ensure accurate calculation of wage types on payslips, considering various employee contract settings and leave requests. These tests verify correct processing of monthly wage types and multiple leave periods across different months, enhancing payroll accuracy.
Original PR description
This commit adds tests to the `_compute_l10n_ch_swiss_wage_ids` function to verify **Wage Types** in payslips across multiple months and with different **Monthly Wage Types** defined in an employee’s contract, as well as multiple leave requests occurring in different months. task-5906677 Forward-Port-Of: odoo/enterprise#107802
Resolved issues and error corrections
This change reverses a recent update that was incorrectly removing accented characters from Mexican VAT (SAT) documents. The SAT now allows all characters, so Odoo is now reverting to accept the user-entered, accented names as originally intended. This ensures users can accurately input their legally registered names without being blocked.
Original PR description
An accent sanitization feature was introduced in Odoo 18 [1]. It was done because it appeared the SAT replaced certain characters with their unaccented counterpart, but it's not the case. At least…
An accent sanitization feature was introduced in Odoo 18 [1]. It was done because it appeared the SAT replaced certain characters with their unaccented counterpart, but it's not the case. At least today, the SAT allows all characters (pointed out in [2]). This explains why in the past 6 months this feature has been slowly undone [3][4][5], character by character, after customers run into issues. The approach can not work, so we go back to the name with the accents the user puts on the partner. Users need to put the correct, legally registered name in Odoo. If it doesn't work then they can adapt it as needed. This way the user is in full control, and we don't block them. This reverts the whole accent sanitization saga: - Revert "[FIX] l10n_mx_edi - More accented characters accepted by SAT", this reverts commit 46cc41ddd258e80372478a746ea79d154a5931d9. - Revert "[FIX] l10n_mx_edi: Fix accents in legal name", this reverts commit dcbd8797667b5be88f48045e48da86ac42db362c. - Revert "[FIX] l10n_mx_edi: Fix accents in legal name", this reverts commit 32b8333fd3f813ec3188394c2634129e3fbfe31d. - Revert "[FIX] l10n_mx_edi: Fix accents in legal name", this reverts commit 05ed1fb9059bd1459e38dc00b041cada6bf06ac4. This also removes the unused frozendict import to make "Check Style" happy. opw-5915515 [1] https://github.com/odoo/enterprise/pull/95207 [2] https://github.com/odoo/enterprise/pull/107960 [3] https://github.com/odoo/enterprise/pull/96043 [4] https://github.com/odoo/enterprise/pull/106557 [5] https://github.com/odoo/enterprise/pull/107677 Closes odoo/enterprise#107960 Forward-Port-Of: odoo/enterprise#108189
This update corrects an issue where manually created receipts were incorrectly merged into existing transfers without a procurement group, leading to disorganized workflows. The change ensures that each manual receipt creates its own independent transfer operation, improving order management and reducing errors in multi-step processes.
Original PR description
*: purchase_stock Issue Before This Commit: ====================== In a `multi-step` configuration, while validating a transfer that has no `procurement group`, its next operation (Input → QC →…
*: purchase_stock Issue Before This Commit: ====================== In a `multi-step` configuration, while validating a transfer that has no `procurement group`, its next operation (Input → QC → Stock) is merged into an existing transfer that also lacks a procurement group, 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 `group_id` 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 `group_id` 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 procurement group. After this Commit: ====================== The `_search_picking_for_assignation()` method now skips searching for existing pickings when moves lack a `procurement.group`. The `_key_assign_picking()` method groups moves by their `originating picking` instead of the partner, preventing merges between unrelated transfers without a procurement group. This ensures each manual transfer creates its `own next operation` in multi-step routes. Task-ID: 5242340 Forward-Port-Of: odoo/odoo#235423
This update resolves an issue where scanning packaging barcodes didn't correctly associate with related lots, leading to incorrect inventory tracking. The fix ensures that packaging barcodes accurately link to the correct lots during scanning, improving the accuracy of stock movements.
Original PR description
When scaning a lot after a packaging, the lot won't recognize the packaging and will not work properly ### Steps to reproduce: * In the settings enable packagings * Create a storable product P with…
When scaning a lot after a packaging, the lot won't recognize the packaging and will not work properly ### Steps to reproduce: * In the settings enable packagings * Create a storable product P with Units as uom, a barcode and tracked by lots * Create new lots with barcode for Product P * Inventory > Configuration > Product > Units & Packagings * Click on pack of 6 > Packaging Barcodes > New * Create one for your product with a different barcode * Go to barcode > Operations > eg. internal transfer > New * Scan packaging barcode * Scan one of the lots -> Issue, the lot create a new line, and will not find the packaging ### Observation: When scanning a barcode, it will first try to find a match with existing lines, In our case, it will find a match with the line of the packaging, but since the line is considered as "completed" since there was no expected quantity since we create a new picking: https://github.com/odoo/enterprise/blob/13d815457d47846d5391c9a2dc1ed244ef64b6c4/stock_barcode/static/src/models/barcode_picking_model.js#L1497-L1501 It will erase the line, to avoid to overfill a completed line: https://github.com/odoo/enterprise/blob/13d815457d47846d5391c9a2dc1ed244ef64b6c4/stock_barcode/static/src/models/barcode_model.js#L1459-L1460 and since, it decided to ignore that line, it will not find another lines, and will create a new one : https://github.com/odoo/enterprise/blob/13d815457d47846d5391c9a2dc1ed244ef64b6c4/stock_barcode/static/src/models/barcode_model.js#L1535 Additional Issues ----------------- Issue 1 : When scaning a packaging, lot1, packaging, lot2, all the packagings will be linked to the first lot, which doesn't allow us to scan multiple lots. Issue 2 : When having sublines with different uoms, it will add the quantity without considering the differences in uoms ### Steps to reproduce: * In the settings enable packagings * Create a storable product P with Units as uom, a barcode and tracked by lots * Create new lots with barcode for Product P * Inventory > Configuration > Product > Units & Packagings * Click on pack of 6 > Packaging Barcodes > New * Create one for your product with a different barcode * Create a packaging 2 with barcode for product A * Go to barcode > Operations > eg. internal transfer > New * Scan packaging 1 barcode * Scan one of the lot 1 * Scan packaging 1 * Scan lot 2 -> Issue 1, the packaging 2 will be link to lot 1, it won't be possible to link any packaging to another lot. * Scan packaging 2 -> Issue 2, it create a subline (excpeted), but the sum that appear on the main grouped line is wrong, it doesn't considere the difference in uoms ### Observation: Issue one : When scanning a barcode, it will first try to find a match with existing lines, since the uom is the same it will not be erased by the full line check https://github.com/odoo/enterprise/blob/13d815457d47846d5391c9a2dc1ed244ef64b6c4/stock_barcode/static/src/models/barcode_model.js#L1456-L1460 and since, it found a line, it will just add it's self to the line Issue Two: When creating the group lines it will first calculate the sum of all the quantities: https://github.com/odoo/enterprise/blob/8774388a7b1b2ca2c08c752026ac1a20dbc10347/stock_barcode/static/src/models/barcode_model.js#L248-L254 And after inside of groupSublines it will choose the main line and it's uom and use the previous sum for the total quantity: https://github.com/odoo/enterprise/blob/8774388a7b1b2ca2c08c752026ac1a20dbc10347/stock_barcode/static/src/models/barcode_picking_model.js#L1456-L1461 opw-5189492 opw-5408372 Forward-Port-Of: odoo/enterprise#98701
This update corrects a reporting issue with Italian invoices (`l10n_it_edi`) by ensuring the total invoice amount (`ImportoTotaleDocumento`) is always displayed in EUR, as required by Italian tax regulations. This ensures accurate reporting and compliance with government standards.
Original PR description
With an `l10n_it` company: - Create an invoice in a foreign currency and export the XML. In the XML, the field `ImportoTotaleDocumento` is expressed in the invoice currency, while `Divisa` is set to…
With an `l10n_it` company: - Create an invoice in a foreign currency and export the XML. In the XML, the field `ImportoTotaleDocumento` is expressed in the invoice currency, while `Divisa` is set to the company currency. `ImportoTotaleDocumento` must be expressed in EUR, as stated in the following document: https://www.agenziaentrate.gov.it/portale/documents/20143/0/10FAQ+pubblicate+il+19+luglio+2019+(aggiornate+il+1+luglio+2021).pdf/6e8acb34-b7c5-730e-6a39-79c0a296e02b > L'art. 21, comma 2, lettera l) del d.P.R. n. 633/72 specifica che > “aliquota, ammontare dell'imposta e dell'imponibile con arrotondamento al centesimo di euro”. > Conseguentemente, se la fattura è emessa da soggetti residenti o stabiliti il codice da inserire nel campo `<Divisa>` > deve essere obbligatoriamente “EUR”. > Article 21, paragraph 2, letter (l) of Presidential Decree No. 633/72 specifies that > “the tax rate, the amount of the tax, and the taxable amount must be stated with rounding to the euro cent.” > Consequently, if the invoice is issued by resident or established taxpayers, the code to be entered in the `<Divisa>` > field must mandatorily be “EUR”. As a result, we now use the **company currency amount** for the `ImportoTotaleDocumento` field (assuming the company currency is always EUR for `l10n_it`). Ticket [link](https://www.odoo.com/odoo/project.task/5913088) opw-5913088 Forward-Port-Of: odoo/odoo#249272 Forward-Port-Of: odoo/odoo#247537
This update fixes an issue where shipping capacity percentages were inaccurate in batch transfers. The change ensures that each batch's capacity is calculated correctly, providing users with reliable data for planning and managing shipments. This improves the accuracy of inventory tracking and dispatch management.
Original PR description
## Issue Before This PR: The fields `used_weight_percentage` and `used_volume_percentage` in the list view were showing incorrect values. These fields were incorrectly aggregating totals across all…
## Issue Before This PR: The fields `used_weight_percentage` and `used_volume_percentage` in the list view were showing incorrect values. These fields were incorrectly aggregating totals across all batches, as the calculation of `estimated_shipping_weight` and `estimated_shipping_volume` was not handled per batch, resulting in wrong percentages. ## Steps to Reproduce: - install inventory module and enable settings for batch transfers and dispatch management, - add two batch records with vehicles assigned (having weight or volume capacity), and transfers having products with weight or volume defined - Observe different values of weight % or volume %, in form and list view. ## Cause of the Issue: In the method `_compute_estimated_shipping_capacity` the computation loop referenced all records together, causing totals to be shared across batches. ## With This PR: Each batch now computes its own estimated shipping weight and volume correctly, ensuring correct per-batch values consistent with the form view and match what users see when opening individual records. Backport of [commit](https://github.com/odoo/odoo/pull/227166/changes/a709e84d8357a622198a8ac0a0199af9b16f56e7) Forward-Port-Of: odoo/odoo#249239
This update resolves an issue where users weren't receiving helpful error messages when attempting to print resumes with invalid templates. The fix adds detailed tracebacks to guide developers in identifying and correcting template problems, improving the user experience and troubleshooting efficiency. This ensures that errors are clearly communicated, leading to faster resolution times.
Original PR description
Currently, when a user tries to print a resume with an invalid template there’s no traceback to show what went wrong. **Steps to produce:** * Install `hr` with demo data * Modify the view…
Currently, when a user tries to print a resume with an invalid template there’s no traceback to show what went wrong. **Steps to produce:** * Install `hr` with demo data * Modify the view `report_employee_cv` by adding `<div t-if=o.no/>` * Print resume of any employee **Observed Behavior:** Currently it only shows the error in [1], with no context or traceback to explain what went wrong. **Root cause:** * This happens because the route doesn’t include the website parameter. Without it, the system treats the route as non–front end [2], so the error handler never reaches [3].That means [4] never loads the templates [5], and the browser just gets a plain response at [6]. **Solution:** * Catching and raising UserError shows appropriate traceback. **Before:** <img width="1606" height="796" alt="image" src="https://github.com/user-attachments/assets/d5432fbf-d016-46a9-bade-8e8408848c66" /> **After:** <img width="1832" height="928" alt="image" src="https://github.com/user-attachments/assets/6f0413ca-a82a-487d-888f-81be6f0fab03" /> [1]: https://drive.google.com/file/d/1qJLkFGw4bEclqKihdUI-4bjJofdFArEc/view?usp=sharing [2]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L386 [3]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L611 [4]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L573-L576 [5]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/views/http_routing_template.xml#L139 [6]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L575 Related: https://github.com/odoo/enterprise/pull/100142 opw-5167898 Forward-Port-Of: odoo/odoo#237262
This update fixes a problem where users received a generic error message when printing invalid PDF reports. Now, when an error occurs, a detailed traceback is displayed, making it easier to identify and resolve the issue with the document layout. This improves the user experience and troubleshooting for payroll reports.
Original PR description
Currently, when a user tries to print a PDF report with an invalid document layout template, there’s no traceback to show what went wrong. **Steps to produce:** * Install payroll with demo data. *…
Currently, when a user tries to print a PDF report with an invalid document layout template, there’s no traceback to show what went wrong. **Steps to produce:** * Install payroll with demo data. * Settings > Configure Document Layout then Edit Layout * Add non-existent field `<div t-if='o.no'/>` * Payroll > All payslips > print any payslip **Observed Behavior:** * Currently it only shows the error in [1], with no context or traceback to explain what went wrong. **Root cause:** * This happens because the route doesn’t include the website parameter. Without it, the system treats the route as non–front end [2], so the error handler never reaches [3].That means [4] never loads the templates [5], and the browser just gets a plain response at [6]. **Solution:** * Catching and raising UserError shows appropriate traceback. **Before:** <img width="1601" height="507" alt="image" src="https://github.com/user-attachments/assets/f7f208f0-cdd7-410e-87e7-32a9651df9d8" /> **After:** <img width="1847" height="928" alt="image" src="https://github.com/user-attachments/assets/c73522d6-2632-422b-b1d1-234e6c61ed2e" /> [1]: https://drive.google.com/file/d/1qJLkFGw4bEclqKihdUI-4bjJofdFArEc/view?usp=sharing [2]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L386 [3]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L611 [4]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L573-L576 [5]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/views/http_routing_template.xml#L139 [6]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L575 Related:https://github.com/odoo/odoo/pull/237262 opw-5167898 Forward-Port-Of: odoo/enterprise#100142
This update resolves an issue where scale readings were inaccurate due to a change in how data was being transmitted. Specifically, the system was receiving 'results' instead of 'values,' leading to incorrect weight displays. This ensures accurate scale measurements for IoT integrations.
Original PR description
This PR fixes the lack of compatibility with the new event manager code sending result instead of value, fixing the weighing stuck at 0 in some situations Forward-Port-Of: odoo/enterprise#108043 Forward-Port-Of: odoo/enterprise#107974
This update resolves an issue where Peppol invoices weren't correctly processed if the specific module wasn't installed. The import logic for self-billing invoices has been moved to the core `account_peppol` module, ensuring consistent and accurate handling of Peppol invoices for all users. This improves the reliability of our Peppol integration.
Original PR description
At the moment, the Peppol AP accepts incoming self-billing invoices for all 18.0 users, but if the `account_peppol_selfbilling` module is not installed on the database, incoming self-billing invoices are not decoded correctly, and end up as as vendor bills rather than sales documents. This is because the import logic for self-billing invoices is in `account_peppol_selfbilling` at the moment. To solve this issue, we move the import logic to `account_peppol`, as well as related tests. task-none Forward-Port-Of: odoo/odoo#247796
This update fixes an issue where the stock valuation calculation was incorrect when creating purchase orders with multiple moves for the same product within the same picking. The fix ensures accurate valuation by preventing double-counting of quantities when stock valuation smart buttons are used, ultimately improving inventory accuracy.
Original PR description
**Steps to reproduce:** - create a storable avco automated product - in the purchase tab, select control policy : "on invoice quantitites" - create and confirm a purchase order for 100 qty at 1 unit…
**Steps to reproduce:** - create a storable avco automated product - in the purchase tab, select control policy : "on invoice quantitites" - create and confirm a purchase order for 100 qty at 1 unit price - on the picking, unhide the description column - change the description for the move - go back to the purchase order and change the quantity to 105 - (because we changed the description, the new move created with a quantity of 5 is not merged to the existing one of 100 and we now have two moves on the picking) - create and confirm the bill - validate the picking - select the valuation smart button **Current behavior:** the svl with a quantity of 100 has a total value of 105 the svl with a quantity of 5 has a total value of 105 **Expected behavior:** the svl with a quantity of 100 should have a value of 100 the svl with a quanitty of 5 shoul have a total value of 5 **Cause of the issue:** When the picking is validated, action_done is created on the two moves. In the stock_account override: - first the super method is called As a consequence the state of the two moves becomes 'done' and the qty_received of the linked purchase order line becomes 105. - then product_price_update_before_done is called on the two moves before creating the svls. https://github.com/odoo/odoo/blob/2f00b0085574653ca1a8f734ef91893a4a1c1a7c/addons/stock_account/models/stock_move.py#L352 Inside product_price_update_before_done, for each move, we call _get_price_unit. https://github.com/odoo/odoo/blob/2f00b0085574653ca1a8f734ef91893a4a1c1a7c/addons/stock_account/models/stock_move.py#L426 For the first move, in the purchase_stock override of _get_price_unit : - to get the received qty we call _get_qty_received_without_self() https://github.com/odoo/odoo/blob/2f00b0085574653ca1a8f734ef91893a4a1c1a7c/addons/purchase_stock/models/stock_move.py#L50 and because the super method of action_done was already called, qty_received of the purchase order line is 105, so _get_qty_received_without_self will return 5. https://github.com/odoo/odoo/blob/2f00b0085574653ca1a8f734ef91893a4a1c1a7c/addons/purchase_stock/models/stock_move.py#L108-L113 So received_qty is 5 and later remaining_qty will be 100 https://github.com/odoo/odoo/blob/dc57ea4d306f8745d37f2c5d2c3d3fa4bcaf7253/addons/purchase_stock/models/stock_move.py#L86 - but because no svl was created yet receipt_value will stay 0 and later remaining_value will be 105 https://github.com/odoo/odoo/blob/dc57ea4d306f8745d37f2c5d2c3d3fa4bcaf7253/addons/purchase_stock/models/stock_move.py#L55-L60 Therefore price_unit will be 1.05 (105/100) instead of 1 https://github.com/odoo/odoo/blob/2f00b0085574653ca1a8f734ef91893a4a1c1a7c/addons/purchase_stock/models/stock_move.py#L95 For the second move, the problem is the same and the price unit ends up being 21 (105/5) **fix** We do not take into account the move(s) for the same product of the same picking in the remaining value (because svls are not created yet) so we should not take them into account in the remaining quantity. the problem is very similar to https://github.com/odoo/odoo/pull/235601 In this other PR it happend because we had multiple move for the same product because they were in a batch, and in this PR we have the issue because we have multiple move for the same product because they didn't merge due to the description difference. opw-5429501 Forward-Port-Of: odoo/odoo#247640
This update fixes an issue where table menus would sometimes overlap with adjacent cells, particularly when viewing partial table views. Now, table menus appear correctly when hovering over list elements within table cells, ensuring a smoother and more reliable user experience.
Original PR description
**Current behavior before PR:** - Table menu handlers could overflow into adjacent table areas when the targeted part of the table was only partially visible within the container. - When a table cell contained a list, hovering over the list element did not display the table UI menus, even though the mouse was inside the cell. **Desired behavior after PR is merged:** - Use a local overlay for the table menu to prevent overflow into adjacent cells. - Table UI menus are now correctly displayed when hovering over list elements inside a table cell. task-5353518 Forward-Port-Of: odoo/odoo#249261 Forward-Port-Of: odoo/odoo#240342
This update ensures that freight charges are accurately reflected on commercial invoices generated for international UPS shipments. Previously, invoices were set to $0 for freight, which caused issues with customs clearance. The fix adds the necessary freight charge information to the shipment request, ensuring accurate invoicing and smoother customs processing.
Original PR description
Issue ----- For international deliveries, the commercial invoice used for customs does not include the freight charges (it is set to 0). Steps to reproduce ----- - Create an international UPS sale - Confirm the delivery - Open the "UPSCommercialInvoice.pdf" file > In the price breakdown, freight is set to 0.0 Cause ----- It has to be specified in the `ship` request as `ShipmentServiceOptions.InternationalForms.FreightCharges.MonetaryValue` (source https://docs.rocketshipit.com/rs/docs/ups-api-parameters.html#shipment) Expected result ----- <img width="1912" height="963" alt="image" src="https://github.com/user-attachments/assets/170e49f7-6575-4524-b186-3829f4c20430" /> ----- Ticket: opw-5135494 Forward-Port-Of: odoo/enterprise#105505
This update resolves a crash in the HTML Editor component caused by overly aggressive sanitization of data attributes. The fix involves temporarily encoding and decoding these attributes during sanitization to prevent removal, ensuring the editor functions correctly. This improves stability and prevents disruptions to users.
Original PR description
Prior to this commit, since DOMPurify v3.1.2 (and more precisely since usage of v3.1.5 in Odoo), the JS sanitization process aggressively removes html attributes with `-->`, `<style` and `<title` for…
Prior to this commit, since DOMPurify v3.1.2 (and more precisely since usage of v3.1.5 in Odoo), the JS sanitization process aggressively removes html attributes with `-->`, `<style` and `<title` for security reasons (see [1]). However `html_editor` embedded components use `data-attributes` (`data-embedded-props` and `data-embedded-state`) to store various kind of data as a JSON string. Obviously, such JSON strings easily match the DOMPurify regex and these attributes are therefore removed, which results in an Editor crash. There are multiple reasons why such values are acceptable as is for the `html_editor` usage: - only `HTMLElement` instances are sanitized, never a string, therefore there is no `DOMParser` to trick with invalid HTML. - values in these attributes are always/exclusively parsed as JSON strings, and the editor will crash if the value is not a legit JSON. - values in these attributes are HTML escaped by the python sanitizer when the serialized html is sent to the server. - values in the JSON parsed object are at worst rendered as plain text (never as HTML or other parsed formats). - values in the JSON parsed object are never executed as JS (only serializable primitives are stored). Therefore, the suggested solution is to encode the values during sanitization, and decode just after, to keep the rest of the codebase simple and explicit. [1]: https://mizu.re/post/exploring-the-dompurify-library-hunting-for-misconfigurations#dompurify-gt-3.1.2-safe-for-xml task-5960707 Forward-Port-Of: odoo/odoo#250210