Thursday, August 20, 2026
27 changes · saas-19.3
Enhancements to existing features
Point of Sale receipts now consistently show the taxable base amount for each tax group, returning to the clearer receipt layout used in Odoo 19.0. This helps customers and staff understand how each tax amount was calculated, especially when multiple taxes share the same base.
Original PR description
Revert the receipt tax summary design back to the 19.0 format, ensuring that the base amount is always displayed for each tax group. Before this commit, when all tax groups shared the same tax base, the base amount was hidden, leading to a flat tax listing. Now, the template always renders the tax groups in the format: "Tax [Name] on [Base Amount] [Tax Amount]" task-id: 6296906 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272831 Forward-Port-Of: odoo/odoo#270749
Resolved issues and error corrections
The Point of Sale dashboard cards now keep their small graphs aligned at the bottom, even when cards show different amounts of information. This makes the dashboard easier to scan and gives users a cleaner, more consistent view.
Original PR description
In the POS config dashboard kanban view, cards could display a variable number of data lines (e.g. session dates, opening, sold, ongoing amounts, or closing date). Because the graph was placed right below the text content without vertical pushing, graphs across cards in the same row ended up vertically misaligned. Fix this by adding `d-flex flex-column` to the card template and `mt-auto` to the graph container wrapper so that graphs are always pushed to the bottom of the card, ensuring consistent alignment regardless of the number of displayed lines. task-id: 6424698 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Features or functions removed from Odoo
Old survey page logic that no longer had any visible effect was removed after the survey interface was redesigned. This cleanup reduces the chance of future errors and keeps the survey module easier to maintain, with no expected change for users.
Original PR description
Here https://github.com/odoo/odoo/commit/719e72f6f44f01c360ef44719404bf47754a8f2d we redesigned client facing survey view. And we removed those icons that are being used by this piece of code, and due to that, actually, this code does nothing. We noticed it via a traceback occurring in saas-19.5 during the recently material symbol icons conversion https://github.com/odoo/odoo/commit/c5a40a608280017ae9ea8f9e9e1c59f778d629ae, which was accessing the class in the wrong manner. Instead of fixing the traceback in saas-19.5, this commit removes the code from the place where it becomes useless. Task-6421899
This fixes an issue where colors from an outer table could incorrectly overwrite the colors of a table nested inside it. Users editing rich text content will see nested tables keep their intended formatting after the editor processes the content.
Original PR description
Problem: When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells…
Problem:
When a `table` with a `color`/`backgroundColor` contains a nested `table`, `distributeTableColorsToAllCells` propagates the outer table's color to every `td` in the subtree, including cells belonging to the inner table. The inner table's own color is then discarded since its `td`s already have a value.
Cause:
`table.querySelectorAll("td")` returns every `td` in the entire subtree, not just the table's own direct cells.
Solution:
Scope the selected `td`s to `td.closest("table") === table`, so a table's color is only distributed to its own cells.
Steps to reproduce:
1. Add a `background-color` to an outer `table`.
2. Nest a `table` with a different `background-color` inside one of its cells.
3. Load/normalize the content in the editor.
4. Observe both tables' cells carry the outer table's color.
opw-6438972
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#282794
Forward-Port-Of: odoo/odoo#281413The employee attendance kiosk no longer loads an unnecessary presence status component. This reduces extra resource loading in the kiosk view and helps keep the attendance experience leaner without changing user-facing functionality.
Original PR description
This commit removes the hr_attendance_presence_status.js file from the kiosk bundle, as it is not needed in the kiosk view and can cause unnecessary loading of resources. task-6468972 Forward-Port-Of: odoo/odoo#282987 Forward-Port-Of: odoo/odoo#282410
Peppol invoice XML now uses the reference from the actual invoice contact when one is set, instead of always using the parent company reference. This helps ensure e-invoices carry the expected buyer information and reduces routing or validation issues for customers with multiple contacts.
Original PR description
**Steps to reproduce:**
* Set up a French company and configure Peppol E-invoicing.
* Install `account_edi_ubl_cii` module.
* Create a company partner (customer) and set a **Reference** value on the company contact under
**Customer** -> **Settings** -> **Sales and Purchase**.
* Create a child contact under that company and set a different Reference value.
* Create an invoice using the child contact as the invoice partner and confirm the invoice.
* Send it via Peppol.
**Observed Behaviour:**
* The BuyerReference in the generated XML contains the reference of the parent
(commercial partner) Instead of the child contact used on the invoice.
**Cause:**
* The buyer reference was taken from the commercial partner instead of the
invoice partner.
**Fix:**
* Update the condition to use the invoice partner's reference when available;
Otherwise, fall back on the commercial partner's reference.
opw - 6330649
Forward-Port-Of: odoo/odoo#273700The profile viewer now displays the profile name even when only one profile is open. This helps users distinguish between profiles when they have several browser tabs open, reducing confusion and navigation mistakes.
Original PR description
The name of the profile is only displayed when the viewer has multiple profiles open. It's not displayed when opening a single profile. If you have many of them open in different browser tabs, the name would help knowing which is which. ## Before <img width="527" height="77" alt="image" src="https://github.com/user-attachments/assets/26706115-dc99-40af-82b1-29e017051403" /> ## After <img width="527" height="77" alt="image" src="https://github.com/user-attachments/assets/46fd85d9-3558-4b64-8fdf-52bf372f4c65" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an automated walkthrough that verifies creating a missing website page. The change helps keep quality checks reliable so page creation behavior remains protected from regressions.
Original PR description
runbot-944311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278652
Point of Sale now correctly handles manually paid negative orders, such as refunds paid by card. This prevents the system from wrongly switching to a customer account flow and blocking validation with an unnecessary customer prompt.
Original PR description
Validating a negative order manually paid with a standard method (e.g., Card) mistakenly triggers the fast payment fallback. The system wrongly assumed any single negative payment line was an auto-generated unsettled due. As a result, if the first configured payment method is "Customer Account", validation is incorrectly blocked by a popup asking for a customer. This commit restricts the fast payment trigger for negative amounts to only apply when the existing line is specifically a 'pay_later' type. task-6443347 Forward-Port-Of: odoo/odoo#281238
Razorpay payment captures and refunds now use the original transaction reference when processing follow-up actions. This helps avoid failed or mismatched payment operations, improving reliability for businesses using Razorpay.
Original PR description
Forward-Port-Of: odoo/odoo#282554
The SMS Marketing screen no longer shows the insert-field option when a message is read-only. This prevents users from hitting an error when viewing SMS campaigns that are already sent or being sent.
Original PR description
Steps to reproduce ---------------------------------------- 1. Install the SMS Marketing module (mass_mailing_sms). 2. Open any SMS Marketing record in the "Sent" or "Sending" stage. 3. Click on the…
Steps to reproduce ---------------------------------------- 1. Install the SMS Marketing module (mass_mailing_sms). 2. Open any SMS Marketing record in the "Sent" or "Sending" stage. 3. Click on the "Insert Field" button. Observation ---------------------------------------- Traceback Occurs: ``` TypeError: Cannot read properties of null (reading 'getRootNode') ``` Issue ---------------------------------------- The SMS widget displays the "Insert Field" button even when the SMS message field is readonly. The button relies on the textarea reference to open the dynamic fields popover, but the textarea is only rendered in editable mode. The readonly behavior of the text field can be seen here: https://github.com/odoo/odoo/blob/ccce9fcc79edcfb1f310b49a16de8235d987b74b/addons/web/static/src/views/fields/text/text_field.xml#L5-L7 However, the SMS widget still renders the "Insert Field" button without checking whether the message field is readonly: https://github.com/odoo/odoo/blob/ccce9fcc79edcfb1f310b49a16de8235d987b/addons/sms/static/src/components/sms_widget/fields_sms_widget.xml#L6 As a result, clicking the button in readonly mode tries to access an unavailable textarea reference to open the dynamic fields popover, causing a traceback. Solution ---------------------------------------- Hide the "Insert Field" button when the SMS message field is readonly, preventing the dynamic fields popover from being opened when the textarea reference is unavailable. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283125 Forward-Port-Of: odoo/odoo#282845
This fixes how Italian VAT carryover amounts are classified in monthly VAT reports. Debit carryovers will no longer appear in the credit carryover section, helping companies avoid incorrect tax return reporting.
Original PR description
With a l10n_it company: - Create an invoice for december, create the tax return closing entry for this period. On the monthly VAT Report of january the carryover is declared in section VP9 which is supposed to store credit carry over not debit. opw-6354509 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279471
This fix prevents the calendar from crashing when a user views a monthly calendar after switching companies and attendee schedules cannot be found. Instead of showing an error, the system now handles the missing schedule information safely so users can continue using the calendar.
Original PR description
Currently, an error occurs when a user opens the calendar. Steps to Reproduce: - Install the `hr_calendar` module. - Go to `Employees` and create an `employee`. - Under the `Settings tab`, set the…
Currently, an error occurs when a user opens the calendar. Steps to Reproduce: - Install the `hr_calendar` module. - Go to `Employees` and create an `employee`. - Under the `Settings tab`, set the employee's `user` to `Administrator`. - Create a `new company` and switch to it. - Open the `Calendar` and set the `scale` to `Month`. `TypeError: reduce() of empty iterable with no initial value` When the user opens the calendar, it fetches the unusual days for the selected attendees. By default, the current user's partner is set as an attendee [1]. It then computes the schedule for the attendee [2], which returns an empty dictionary [3] because the linked employee belongs to a different company than the current company, as restricted by the domain [4]. This empty dictionary is then passed to reduce() to intersect the schedules, which raises an error because the iterable is empty. This commit ensures that when no schedule is found for the attendees, an empty set is returned. [1]: https://github.com/odoo/odoo/blob/658018684d781fef8bf77a77f1e050d1eb16937c/addons/hr_calendar/models/calendar_event.py#L38-L40 [2]: https://github.com/odoo/odoo/blob/658018684d781fef8bf77a77f1e050d1eb16937c/addons/hr_calendar/models/res_partner.py#L123-L130 [3]- https://github.com/odoo/odoo/blob/658018684d781fef8bf77a77f1e050d1eb16937c/addons/hr_calendar/models/res_partner.py#L40-L42 [4]- https://github.com/odoo/odoo/blob/658018684d781fef8bf77a77f1e050d1eb16937c/addons/hr_calendar/models/res_partner.py#L19-L25 sentry-7672490836 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Clicking a table of contents entry in the HTML editor now scrolls the related heading into a more visible position. This helps users quickly confirm they reached the right section instead of thinking the click did not work.
Original PR description
When clicking on a title in the TOC, we auto-scroll to that section of the HTML, allowing users to read that part. Since [1], scrollIntoView is replaced to consider top-aligned sticky elements. As a result, instead of scrolling to make it comfortable to read the section, it stops as soon as the title is visible. Unless you are really attentive at the bottom of the screen, it can look like the scrolling did not work. This commit computes the appropriate offset to make the TOC heading more visible after scrolling. [1]: https://github.com/odoo/odoo/commit/f5cf8565e7d09edd3a29fd95537381fb70d75785 Task-6394193 Forward-Port-Of: odoo/odoo#278304
Regular Sales users can now see the three-dot menu on product cards in the Product Catalog. This restores access to actions they were already allowed to use elsewhere, avoiding unnecessary administrator rights for everyday sales work.
Original PR description
**Steps to Reproduce:** 1. Give the logged in user "Sales / User: Own Documents Only" access rights 2. Open the Product Catalog (from a Sales Order line) 3. The three-dot menu on a product card is not visible when you hover over it 4. Change user rights with "Sales Administrator" access rights, the three-dot menu appears as expected **Issue:** The three-dot menu on the Product Catalog kanban card is restricted to the Sales Administrator group, even though the actions it exposes (edit product, availability, etc) are already accessible to regular Sales users through other menus/views. **Why this happens:** The view `product.view.kanban.catalog.inherit.sale` sets the `groups` attribute to `sales_team.group_sale_manager`, restricting the menu behind Administrator rights instead of the base Sales access group opw-6416629 Forward-Port-Of: odoo/odoo#279400
This fixes an internal automated test for Odoo's messaging system that could fail unpredictably on slower or heavily loaded machines. The test now waits until all expected peer connections are ready before checking results, reducing false failures and improving release confidence.
Original PR description
Before this commit, "mesh peer to peer connections" fails at random on a loaded machine, counting fewer connections than its ten users make:
[toBe] expected values to be strictly equal
> Expected: 90
> Received: 81
This happens because the test counts the peers as soon as its addPeer calls resolve. addPeer awaits the readiness promise of the peer, which also resolves, with false, when that peer is disconnected. A connection slow to open reaches the recovery watchdog, which tells the other side to drop the peer, drops it locally and adds it back without awaiting it. The awaited promises can therefore all be settled while recovered peers are still connecting.
This commit waits for the mesh to reach its full size before counting, so that a recovery in flight no longer decides the result. With the browser CPU throttled, the test fails about half of its runs before this commit, and none after.
Forward-Port-Of: odoo/odoo#282719Swiss payroll payment files now include the employee beneficiary name for Revolut-related payments. This helps banks process payroll transfers more reliably and reduces the risk of rejected or delayed salary payments.
Original PR description
Forward-Port-Of: odoo/enterprise#126632
Adds automated coverage to ensure Italian VAT report carryover values are handled correctly. This helps prevent regressions in tax reporting calculations without changing the user-facing workflow.
Original PR description
Add test for https://github.com/odoo/odoo/pull/279471 opw-6354509 Forward-Port-Of: odoo/enterprise#127429
This update corrects the title styling shown in website theme preset previews. It ensures business users see an accurate preview when choosing or configuring a website theme, avoiding misleading title sizes.
Original PR description
When the conflict of the forward port [1] was resolved, an error was introduced when the class `fs-4` was replaced by `fs-h4`. This commit fixes the class. [1] https://github.com/odoo/odoo/pull/279324 Forward-Port-Of: odoo/odoo#281995
The product catalog opened from field service tasks now gives more space to the unit of measure column. This makes product information easier to read and aligns the Enterprise interface with the related Community update.
Original PR description
Steps to produce: --- - Install `Field service` module. - Create a task and open it. - From the task open the catalog from smart button. Update the Product Catalog UI to match the Community PR changes. community PR: https://github.com/odoo/odoo/pull/267118 opw-6253382 --- Forward-Port-Of: odoo/enterprise#128146 Forward-Port-Of: odoo/enterprise#121139
Fixed an issue that could stop database neutralization when multiple active TikTok shops existed. The process now removes real shop references while keeping each record unique, allowing neutralization to complete reliably.
Original PR description
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error:…
Steps to produce: --- - Install sale_tiktok module. - Create two active tiktok.shop records. - Run the database neutralization command. Issue: --- - Neutralization fails with a PostgreSQL error: ```py duplicate key value violates unique constraint tiktok_shop_unique_active_shop` DETAIL: Key (tiktok_shop_ref)=(1) already exists. ``` Root cause: --- - At [1], we are setting `tiktok_shop_ref = 1` for all `tiktok_shop` records. Because `tiktok_shop` enforces a partial unique constraint on `tiktok_shop_ref` for active shops [2], setting the same reference value `1` on multiple active shops violates this constraint. Solution: --- - Update sql to assign a row-unique string to each shop. This strips the real shop reference while maintaining uniqueness across active shop records so neutralization completes cleanly. [1]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/data/neutralize.sql#L1-L8 [2]https://github.com/odoo/enterprise/blob/85754b0354b76da8b4d87a3a81dd19679ed35d15/sale_tiktok/models/tiktok_shop.py#L136-L139 opw-6451715 --- Forward-Port-Of: odoo/enterprise#127532
The project forecast button has been moved back to its earlier location after a recent layout change. This restores the familiar interface for users and reduces confusion when accessing project forecasting.
Original PR description
Reverting the position of the project forecast button to the previous one, which was changed in the recent changes. Apply changes up to saas-19.4
Validation messages on Indian employee contracts now reflect the employee's actual pay schedule instead of always referring to a monthly wage. This reduces confusion when allowances exceed wages for contracts with different pay frequencies.
Original PR description
**Steps to reproduce:** - Create an indian employee. - Put total allowance `(basic salary + HRA + standard ALW + Perf bonus + travel ALW) > wage` - We will get validation error in employee stating that allowance sum can't be greater than wage. **Before:** - We were always showing monthly wage in the validation error, which was confusing to the end user. **After:** - We will use field `version.shedule_pay` to show dynamic validation error message. Task: [6449791](https://www.odoo.com/odoo/project/1251/tasks/6449791) Forward-Port-Of: odoo/enterprise#127477
This fix prevents Mexican payroll processing from failing when a company has no VAT number entered. Payslips can now show the relevant warnings instead of crashing, helping payroll teams continue their work without interruption.
Original PR description
`res.company.vat` is not required and can be `False`. Guard the `len()` call so `_issue_mx_warnings` doesn't crash on payslips for companies without a VAT set.
```py
File "/home/odoo/src/enterprise/saas-19.3/hr_payroll/models/hr_payslip.py", line 1936, in _compute_issues
issues = generate_issue(slip, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 235, in _issue_mx_warnings
if not slip.company_id.l10n_mx_curp and slip._l10n_mx_is_curp_needed():
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.3/l10n_mx_hr_payroll_account_edi/models/hr_payslip.py", line 325, in _l10n_mx_is_curp_needed
or len(self.company_id.vat) == 13
^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object of type 'bool' has no len()
```
Forward-Port-Of: odoo/enterprise#128216Users now get a clear notification if they try to add or edit a dynamic field before choosing where it applies. The editor also handles outdated field selections more safely, reducing interruptions when templates or models change.
Original PR description
The dynamic field editor assumes that an `Applies To` model is always selected and that existing dynamic fields are always valid for the current model. As a result, trying to insert or edit a dynamic field without selecting a model raised an error. Editing an existing dynamic field after changing the selected model could also crash the field selector when the stored field path was no longer valid. Show a notification when users try to insert or edit a dynamic field without selecting a model, and handle invalid field paths when initializing the field selector to avoid UI crashes. Task-6365420 Forward-Port-Of: odoo/odoo#278544
This fix restores the missing delete button on employee records in the timesheet area. It helps HR and timesheet users manage employee records as expected without needing technical workarounds.
Original PR description
task-6468432 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 Forward-Port-Of: odoo/odoo#282781
Long unit of measure names are now displayed properly when adding products from the sales catalog. This prevents important product quantity information from being cut off, making order entry clearer for users.
Original PR description
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the…
Steps to produce: --- - Install `sales` module. - Go to Settings and enable `Units of Measure and Packaging`. - Set a long name for `units` UoM. - Create a Sale Order and add a product via the catalog. Issue: --- - Long UoM names are not fully visible in the catalog view. Root cause: --- - The outer `<div>` has `d-flex` but lacks `w-100`, causing it to overflow its container. Solution: --- - Added `w-100` to the outer `<div>` to prevent overflow. - Adjusted the quantity selector layout for better visibility. Before: --- <img width="388" height="141" alt="image" src="https://github.com/user-attachments/assets/dafae08a-3c9d-4163-8894-daa2e4d26f62" /> After: --- <img width="382" height="154" alt="image" src="https://github.com/user-attachments/assets/abd6f034-be4b-49bf-be9c-c9779de0f30d" /> Enterprise PR: https://github.com/odoo/enterprise/pull/121139 opw-6253382 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282821 Forward-Port-Of: odoo/odoo#267118