Friday, May 22, 2026
30 changes · 19.0
Resolved issues and error corrections
The picking operations report now shows table borders again, making delivery order details easier to read and compare. This fixes a display issue that made rows and columns harder to distinguish when printing warehouse operation reports.
Original PR description
Issue before this commit: ========================= The picking operations report displays the operations table without borders, making it difficult to read and distinguish between rows and columns.…
Issue before this commit: ========================= The picking operations report displays the operations table without borders, making it difficult to read and distinguish between rows and columns. Steps to Reproduce: ========================= - Install the stock module - Create a delivery order with products - Print the picking operations report Cause of the issue: ========================= In this commit (https://github.com/odoo/odoo/commit/21cd7e6), the `o_report_stockpicking_operations` class was added to a div, which removed the table borders. After This Commit: ========================= This change restores the table borders in the operations report, improving readability. Before: <img width="796" height="523" alt="2026-04-17_16-30" src="https://github.com/user-attachments/assets/084861e9-3c5b-4ca7-a237-32a56bf2267d" /> After: <img width="795" height="596" alt="2026-04-17_16-30_1" src="https://github.com/user-attachments/assets/e43ed341-8e8b-47c9-9820-66a53823b26c" /> Task: 5462122
Vendor bill imports from UBL files no longer fail when a Peppol endpoint value has accidental trailing spaces. This reduces avoidable import errors and manual cleanup for accounting teams receiving electronic invoices.
Original PR description
**PROBLEM** When importing a ubl that, for some reason, have trailing space on the text of the EndpointID node, we refuse it. This PR strips the trailing spaces on the import. **STEP TO REPRODUCE** 1. Import a ubl as a bill, with a trailing space in the EndpointID of the other party. 2. Notice the import fail, with the error: The Peppol endpoint (50238597645 ) is not valid. It should contain only letters and digit. opw-6227395 Forward-Port-Of: odoo/odoo#265266
This fix reduces the delay when updating quantities in the product catalog, making changes feel more responsive for users. It helps teams work more smoothly when adjusting product quantities during catalog-based workflows.
Original PR description
opw-5861412 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Invoice reports now calculate section subtotals correctly when prices include tax. This helps customers and accountants see accurate grouped totals on printed or exported invoices, reducing confusion and manual corrections.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Receipts can now use professional deduction percentages without triggering a validation error. This supports realistic accounting cases, such as self-employed workers recording partially deductible travel or ticket expenses, and aligns receipt behavior with vendor bills.
Original PR description
As using deductions on receipts is a plausible accounting situation, such as in the case of self-employed person booking a ticket, there shouldn't be a validation error raised in this case. task-6037582 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Email template banner blocks now keep their left and right spacing after saving and reloading. This prevents banner icons and content from appearing misaligned, improving the consistency of customer-facing emails.
Original PR description
Problem: In email templates, adding a banner/info block and saving then reloading causes the horizontal padding to be lost and the icon to become misaligned. Cause: During save, `convert_inline`…
Problem: In email templates, adding a banner/info block and saving then reloading causes the horizontal padding to be lost and the icon to become misaligned. Cause: During save, `convert_inline` processes the content via `_normalizeStyle`, which iterates over `CSSStyleDeclaration` using index-based iteration. This only yields longhand properties (e.g. `padding-left`, `padding-top`), never shorthands like `padding`. When the shorthand contains `var()` references (e.g. `padding: var(--y) var(--x)`), the browser cannot resolve the longhands and leaves them empty, so they are silently dropped during style extraction. Adding shorthand support to the iterator was not viable, as the rest of the pipeline expects longhand-only styles, and safely converting `padding: var(--y) var(--x)` to longhands is not possible without first resolving the variables. Solution: Replace the `padding` shorthand in the banner template with explicit longhand properties (`padding-top`, `padding-bottom`, `padding-left`, `padding-right`). Steps to reproduce: 1. Open an email template 2. Add a banner/info block 3. Save the template 4. Reload the page 5. Observe horizontal padding is lost and icon is misaligned task-6230530 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue in point of sale where cancelling a Cashdro payment line with the delete button cancelled the payment but left the line visible in a retry state. The line is now removed as expected, reducing cashier confusion and keeping orders cleaner.
Original PR description
Before this commit, if you tried to cancel and delete a Cashdro payment line by clicking the x, the payment would be cancelled but the line would not be deleted, just left in the 'retry' state. After this commit, the payment line is deleted after being cancelled as expected. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents Malta tax migration from crashing when some expected tax records are not present for a company. It helps affected businesses complete upgrades or migrations more reliably without manual intervention for this specific missing-data case.
Original PR description
### Issue: During migration of Malta taxes, the script can fail when certain tax XML IDs are missing for a company. If the XML ID does not exist, `env.ref(..., raise_if_not_found=False)` returns…
### Issue:
During migration of Malta taxes, the script can fail when certain tax XML IDs are missing for a company. If the XML ID does not exist, `env.ref(..., raise_if_not_found=False)` returns None. Trying to combine a recordset with None causes the migration to fail. Due to recent [commit]
### Traceback:
```py
tax_7 |= env.ref(f'account.{company.id}_VAT_S_IN_MT_7_G', raise_if_not_found=False)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 6589, in __or__
return self.union(other)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 6603, in union
raise TypeError(f"unsupported operand types in: {self} | {arg!r}")
TypeError: unsupported operand types in: account.tax() | None
```
###
Solution:
Use a guard check with the walrus operator (:=) to assign and validate the tax record before union.
This ensures that only existing tax records are added to the recordset, preventing the crash.
Ticket [link1](https://www.odoo.com/odoo/project.task/6159300) [link2](https://www.odoo.com/odoo/project.task/6149387)
opw-6159300
opw-6149387This fixes an issue where empty styled table cells in the HTML editor were not selected correctly when using the table move handle. Users can now reliably select and style full tables, even when cells are empty.
Original PR description
#### Description of the issue this PR addresses: - Empty `.o_table` cells containing only placeholder ZWS content were not considered visible - Full table selection via move handle failed to apply `o_selected_td` on styled empty cells #### Desired behavior after PR is merged: - Consider `.o_table` table cells visible Steps to reproduce: - Insert a table - Select it via move handle - Apply any color - Click the move handle again to select the table All table cells should have class `o_selected_td` task-6208949 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
In POS Restaurant, removing a general note now correctly clears the message badge on the “Send to Kitchen” button. This prevents staff from seeing a misleading pending-change indicator after a note has already been removed.
Original PR description
Steps to reproduce:
-----------
- Open POS Restaurant
- Add a General Note
- Remove the General Note
- The message badge on “Send to Kitchen” remains visible
Issue:
-----------
Removing a General Note set `general_note` to `undefined`, which was
detected as a change and kept the badge visible.
Fix:
--------------
Normalize empty General Notes to an empty string ("") so removing a note
restores the correct initial state.
Task-6101501
Related PR: odoo/enterprise#113514
Forward-Port-Of: odoo/odoo#265652
Forward-Port-Of: odoo/odoo#258632Fixed a rounding issue that could cause Jordan POS e-invoices to be rejected by Jofotara because a line discount appeared as a tiny negative amount. The change ensures discount amounts are always reported as non-negative, improving successful invoice submission for affected POS orders and refunds.
Original PR description
Before this commit: 1. Create a POS order with no discount and a quantity that does not divide evenly into the unit price (e.g. price=10.0, qty=3) 2. Send the order to Jofotara Jofotara rejects the…
Before this commit:
1. Create a POS order with no discount and a quantity that does not divide evenly into the unit price (e.g. price=10.0, qty=3)
2. Send the order to Jofotara
Jofotara rejects the invoice because the AllowanceCharge/Amount on the invoice line is a small negative value like -0.000000001 with the error `"EINV_MESSAGE":"discount cannot be negative"`
This happens because _add_document_line_gross_subtotal_and_discount_vals computes the discount as: gross_subtotal - total_excluded_currency
where gross_subtotal goes through two independent rounding steps (round unit price, then round unit_price * qty). When the quantity is indivisible, the reconstituted gross_subtotal can land just below total_excluded_currency by a floating-point epsilon, producing a tiny negative discount. The same subtraction also produces a legitimate negative value for refund lines (negative quantity), which was already handled by abs() in _add_pos_order_discount_vals for the document-level total but was left unguarded at the per-line level.
After this commit:
Apply abs() to vals[f'discount_amount{currency_suffix}'] in _add_pos_order_line_allowance_charge_nodes so that discount_amount_currency is always non-negative.
opw-6183423
Forward-Port-Of: odoo/odoo#265159Website editors no longer see an error when deleting an image from a media list item. When an item has no image, the editor now hides image layout controls and offers an option to add an image back, making page editing smoother and less disruptive.
Original PR description
Before this commit, the deletion of a `s_media_list_item` image triggered a traceback because `SetMediaLayoutAction.isApplied()` attempted to calculate the option's state on a missing element. Steps to reproduce: - Enter edit mode - Drop `s_media_list` snippet - Select the first media item - Delete its image - The image is deleted, but a traceback appears This commit hides media layout options when the item has no image and introduces an add image option instead. task-6229179 Forward-Port-Of: odoo/odoo#265271
The POS product information popup now shows the total available stock for the product template instead of a single variant. This gives staff a more accurate stock view when checking products with variants, reducing confusion during sales.
Original PR description
When opening product info in POS for a product with variants and inventory tracking, Units Available was computed from the selected variant (or first variant), which is incorrect for this popup. It should display the product template available quantity. Partial backport of : 6f3fe739c1af9bbe5f1a61f32431ba5c5aed3e12 Steps to reproduce: ------------------- * Open a POS session. * Long press a storable product with inventory tracking enabled and variants. (e.g. Customizable Desk) > Observation: Units Available shows variant quantity instead of template quantity. Why the fix: ------------ The product info popup is template-oriented and must show template stock values. This fix updates `get_product_info_pos` to use template available quantity for all variants. opw-5703723 Forward-Port-Of: odoo/odoo#250627
The shop page search dropdown now appears above nearby page content instead of being partly hidden. This makes product search suggestions easier to read and use when custom content blocks are placed near the search bar.
Original PR description
On /shop, when a snippet block sits above the searchbar, the search dropdown was rendered partially hidden behind that block (cropped/unreadable items). Steps to reproduce: =================== 1. Go…
On /shop, when a snippet block sits above the searchbar, the search dropdown was rendered partially hidden behind that block (cropped/unreadable items). Steps to reproduce: =================== 1. Go to /shop. 2. Add a snippet block above the searchbar. 3. Type in the searchbar. => Observed: search results appear cropped, with upper items hidden behind the snippet block above. Root cause: =========== the products grid column (`#products_grid`) has `overflow: auto`, https://github.com/odoo/odoo/blob/d9bb1c1dc90f97b63b87ad762fc4ab36abf7e05f/addons/website_sale/static/src/scss/website_sale.scss#L442 which clips any absolutely-positioned descendant that extends past its bounds. The dropdown's containing block is the searchbar `<form>` (position: relative), which lives inside that column. When the dropdown grew (or flipped to dropup) and extended outside the column, the part outside was clipped, and any positioned snippet siblings above the column painted over the clipped area. Fix: ====== while the dropdown is mounted, lift the `overflow: auto` on its ancestor `div.col` so the menu can extend past the column and paint on top of other content. Done from JS so no SCSS rule has to target the searchbar-specific column. opw-6216317 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265558
This fix makes an internal Time Off test use an explicit start date so it no longer fails around midnight due to timezone differences. It improves reliability of automated checks without changing business features or user workflows.
Original PR description
Issue: ----------------------------------- At certain times of the day (e.g., around midnight UTC), the test would fail deterministically ``` test_allocation_stats_with_duplicate_leave_type_names…
Issue:
-----------------------------------
At certain times of the day (e.g., around midnight UTC), the test would fail deterministically
```
test_allocation_stats_with_duplicate_leave_type_names
self.assertEqual(leave_type_no_comp.with_context(employee_id=employee_id).max_leaves, 10)
AssertionError: 0.0 != 10
```
Cause:
-----------------------------------
This occurred due to a timezone mismatch during the test execution. When creating the `hr.leave.allocation`, `date_from` implicitly defaults to `fields.Date.context_today(self)` (which evaluates the date based on the test user's timezone, e.g., Europe/Brussels). However, the `max_leaves` computation in `hr.leave.type` evaluates valid allocations using `fields.Date.today()` as the target date (which strictly evaluates to the UTC date)
At certain times of day, this caused the allocation's `date_from` to evaluate to 'tomorrow' relative to the UTC `target_date`. Because the allocation was technically in the future relative to UTC, it was skipped during the computation causing `max_leaves` to return 0.0 instead of 10.
Solution:
-----------------------------------
Explicitly define `'date_from': date.today()` when creating the allocation in the test case. This perfectly aligns the allocation's starting date with the strict UTC evaluation used by the `max_leaves` computation under the hood.
Runbot Error: [937759](https://runbot.odoo.com/odoo/runbot.build.error/937759)
Related PR: https://github.com/odoo/odoo/pull/261680
Forward-Port-Of: odoo/odoo#265717
Forward-Port-Of: odoo/odoo#265703This update fixes a visual issue where long text in m2m tags' avatar fields would overflow and be cut off. The change adds a 'truncate' class to the spans, ensuring text is neatly cut off with an ellipsis when it exceeds the available space, improving the overall user experience.
Original PR description
Currently, the m2m tags avatar field does not have the truncate class for the spans. When the text is too long, it overflows and the rest is cut off. This commit adds the truncate class to the spans of the m2m tags so that the text is truncated with an ellipsis when it exceeds the available space. task-4809319 https://github.com/odoo/odoo/pull/256817
This update resolves an issue where branch VAT settings were incorrectly inheriting from the parent company, causing confusion and manual VAT adjustments. The change defaults branches to no VAT, ensuring the parent company remains the key provider and simplifies operations. Key settings are now restricted to the base group system.
Original PR description
Branches copied the parent's VAT, which made them their own signing entity and forced users to clear the VAT so the branch would reuse the parent's keys. Default branches to no VAT so the parent remains the key provider. Setting a VAT on a branch still exposes the key settings for the rare case separate keys are needed. Also restrict the key settings to base.group_system task_id - 6087168
This update simplifies the process of creating intercompany sale and purchase documents by removing a redundant step. Previously, the system explicitly generated document sequences, which was causing issues with extensibility. Now, the system relies on the standard sequence assignment process, ensuring greater flexibility and ease of customization.
Original PR description
The intercompany sale and purchase document creation explicitly calls next_by_code to generate document names, even though sequence assignment is already handled in create(). This explicit sequence generation is redundant and reduces the extensibility of the sequence flow. Remove the redundant next_by_code calls and rely on the standard create() flow for sequence assignment. e.g. in custom implementations with separate Quotation and Sale Order sequences, the inter-company flow directly calls next_by_code, bypassing the standard sequence handling. Removing this call has no functional impact since `create()` already generates the sequence.
This update corrects a restriction in the MPF account validation process, allowing employers to manage multiple accounts under the same registration number – a common business practice. Previously, the system incorrectly blocked valid multi-account configurations. This change ensures accurate tracking of employer MPF accounts and simplifies payroll processing.
Original PR description
An employer can legitimately hold multiple employer account numbers under the same MPF registration number. The previous constraint rejected any two MPF schemes sharing the same registration number, blocking valid multi-account configurations. Fix the validation to only restrict the duplicate based on the combination of registration number and employer account number. task-6232561
This update resolves an issue where the VIES validation process incorrectly flagged invoices without VAT as problematic during tax return creation. The fix ensures VIES validation only applies to tax returns where a fiscal position with VAT requirements is present, improving accuracy and preventing unnecessary errors. This ensures proper compliance with VAT regulations.
Original PR description
Vies validation should only occurs with moves having fiscal position with vat required Steps: - With base_vat, and european l10n like BE installed - Make a bill for a partner with no vat or invalid vat - Create a tax return - Open the return -> the 'check_partner_vies' fails opw-6200246
This update resolves an issue where generating a lot in a manufacturing order would reset the intended production quantity back to zero. The fix ensures the quantity is saved before lot generation, preventing this unexpected reset and maintaining accurate production tracking. This improves the reliability of the manufacturing process.
Original PR description
Step to reproduce: - Create a MO with a lot tracked product (enable it in settings) and a work center - Put the quantity to produce to more than 1 - Confirm the MO - Use the smart button to go to the Shop floor - Click on the three dots and click on "Register production / serial" - Put the quantity to produce to 1 and click on "Generate lot" - The quantity to produce is updated to 0, which is not correct, it should stay to 1 Cause: The quantity to produce was not saved before generating the lot, so after the reload triggered by the generation of the lot, the quantity to produce was reset to the last saved value, which is 0. Task-6158833
This update fixes an issue where users couldn't undo the insertion of a prompt banner. The fix ensures that undo functionality correctly removes prompt banners, improving user experience and data consistency. It addresses a bug preventing proper history management within the AI editor.
Original PR description
Problem: After inserting a prompt banner, undo does not remove it. Cause: History commands were ignored when the selection was inside the prompt banner, preventing undo from handling banner insertion. Solution: Handle history commands even when the selection is inside the prompt banner. Steps to reproduce: - Insert a prompt banner using `/prompt` + Enter. - Press Ctrl + Z. - Observe that the banner is not removed. task-6230530
This update resolves an issue where downloading signed documents through the Sign app was failing due to a compatibility problem with the pypdf library. The fix moves the document compression step to the correct object, ensuring compatibility with newer versions of pypdf and preventing errors. This ensures reliable document downloads for users.
Original PR description
This [related PR] introduced a compression pass after calls to mergePage(). However in newer versions of pypdf (>=3.5.2), compress_content_streams() can only be called on pages of PdfWriter. An error would be raised when called on pages of a PdfReader. Steps to reproduce ----- 1. Run Odoo with pypdf>=3.5.2 2. Sign and download a document in the Sign app 3. Traceback occurs Fix ---- This commit moves the compression to the writer object, after the merged page has been added. Related pr: https://github.com/odoo/odoo/pull/261879 runbot-937761 Forward-Port-Of: odoo/enterprise#118111 Forward-Port-Of: odoo/enterprise#117756
This update corrects a visual issue in comparison reports (Balance Sheet, P&L) where total values were incorrectly duplicated in both the line and header sections when 'Add total below sections' was enabled. The change ensures that totals are only displayed when a section is expanded, improving report clarity and accuracy.
Original PR description
Right now when you expland a section in comparison mode like in the Balance Sheet and P&L, if "Add total below sections" is enabled in the report then it shows in both the header and totals sections. This commit clears up that by only showing the value in the line when it's unexpanded, but once it is expanded it is hidden. task-6190986
This update fixes a potential error in the generic tax report that prevented error messages from appearing when dealing with negative net values. The change ensures that the report accurately checks for tax discrepancies, regardless of whether the net amount is positive or negative, improving report reliability.
Original PR description
**Issue:** In the generic tax report, a check is performed on the report lines to ensure that the declared tax amount is consistent with the expected amount. If the difference between the declared tax amount and the expected one is higher than 0.1% of the declared net amount, then a error message is displayed. If the net amount is negative, the error message is never displayed because the computed percentage of the tax difference is negative and therefore lower than 0.1% (i.e. 0.001). opw-6014350 Forward-Port-Of: odoo/enterprise#117990
This update removes a redundant step in creating embedded actions within Odoo. Previously, a separate translation was required, but now that embedded actions automatically inherit their display names, this manual process is no longer necessary. This streamlines the action creation workflow and ensures consistent translations.
Original PR description
Now that `ir.embedded.actions` delegates its display name to the linked action, the manual translation copy on embedded action creation is no longer needed. Related: https://github.com/odoo/odoo/pull/262981 Forward-Port-Of: odoo/enterprise#116793 Forward-Port-Of: odoo/enterprise#116369
This update corrects a translation error in the Odoo Enterprise Gantt view. The button used to toggle display modes was not properly translated, preventing users from seeing the view in their preferred language. This fix ensures all users can consistently access and understand the Gantt view's options.
Original PR description
The title of the button allowing to toggle the display mode in the Gantt view was not translated. This commit adds a getter to compute the title based on the current display mode, and uses it in the template. Issue reported by translator. Forward-Port-Of: odoo/enterprise#117807 Forward-Port-Of: odoo/enterprise#117739
This update resolves an issue where product variant prices didn't automatically update when the cost price was modified. The fix ensures that changes to the cost price immediately trigger an update to the 'On Sale Price,' eliminating the need for manual price list adjustments. This improves accuracy and efficiency in managing product pricing.
Original PR description
When we create a product variant and have a pricelist which is based on the cost price, and change the cost price, the on_sale_price doesn't update. You have the change the price list to other and back to the one you want for it to trigger change because the _onchange_compute_pricing only gets triggered if there's change on pricelist (pricer_sale_pricelist_id), and sales price (lst_price). Steps to Reproduce: 1.Create a pricelist and add a line with "formula" price type, and based on "cost", 2.Create a product variant, and add the pricelist just created. 3.Change the "Cost". The "On Sale Price" doesn't update. 4.You have to change the price list to some other and back to the one you want for the "On Sale Price" to update. To fix the issue, we add the field Cost (standard_price) on api.onchange, so when we change the cost it'll update the "On Sale Price" right away. opw-5947995 Forward-Port-Of: odoo/enterprise#111892
Features or functions removed from Odoo
Odoo removed obsolete internal logic for keeping translated table of contents headings in sync. This reduces duplicate maintenance while preserving the same editing behavior through existing shared functionality.
Original PR description
The plugin `TranslateTableOfContentOptionPlugin` is not needed anymore, the replication between the headers in the content of the `s_table_of_content` and its navbar is now completely handled by the `FieldChangeReplicationPlugin` plugin since a5f1af347b55da8662d6d6802b57e14aab574d78. The test is removed because it is not representative of real edition situation (the nodes it changes are not inside `contenteditable=true` or `o_savable`), and the test added in a5f1af347b55da8662d6d6802b57e14aab574d78 covers this usecase. task-5892636 Forward-Port-Of: odoo/odoo#264325
Miscellaneous changes