Wednesday, July 8, 2026
22 changes · saas-19.1
Enhancements to existing features
The Azerbaijani Manat (AZN) now uses its official symbol, ₼, in the system. This improves display accuracy for users working with Azerbaijani currency and helps ensure printed and on-screen documents look correct.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 task-6112867 Forward-Port-Of: odoo/odoo#262471
When users resize tables in the editor, the horizontal scrollbar now appears on the table itself instead of expanding the whole editing area. Existing resized tables are also updated automatically, so the behavior is consistent when reopening content. This makes table editing smoother and avoids layout issues in the editor.
Original PR description
#### Description of the issue this PR addresses: - Resized tables stored their width on the `table` element. When such tables became wider than the editable area, a horizontal scrollbar appeared on the main editable. #### Desired behavior after PR is merged: - Width handling is now moved to `tbody` so the scrollbar stays on the table itself instead of the editable. - This PR also updates already resized tables when loading the editor to ensure they follow the same behavior. task-5123011 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272977
Resolved issues and error corrections
Pasting document links into an empty message no longer adds an unnecessary blank line at the start. This keeps shared document messages cleaner while still separating links from any existing text.
Original PR description
Before this commit, adding document links always prepended a line break before the generated links. When the composer was empty, this resulted in messages starting with an unnecessary blank line. This commit only inserts a line break when the composer already contains text, avoiding the extra spacing while preserving the separation between existing content and pasted links. task-[5947683](https://www.odoo.com/odoo/project/1519/tasks/5947683) Forward-Port-Of: odoo/enterprise#120952
Previously paused checks for rental stock valuation and Kenyan electronic stock reporting have been restored and updated. This helps ensure stock values now align with vendor bill amounts, reducing the risk of incorrect reporting or inventory valuation going unnoticed.
Original PR description
*: sale_stock_renting, l10n_ke_edi_oscu_stock Re-enable and adapt the tests skipped to fast merge the valuation refactoring made in 08b62a4bbcc6f9a391b2cc00a621ef4c76100229. The stock IO now values the receipt from the vendor bill, so the shared purchase fixtures `l10n_ke_edi_oscu` need to match the values provided in `l10n_ke_edi_oscu_stock` see for instance: https://github.com/odoo/enterprise/blob/ce68644f97ac28568b9497a18079a4ad5ce4a125/l10n_ke_edi_oscu/tests/expected_requests/save_purchase_2.json#L11-L13 Forward-Port-Of: odoo/enterprise#122857
This fix prevents an error when EasyPost returns an empty tracking record while processing shipment tracking links. Users can continue working with deliveries without being interrupted by a system traceback in this edge case.
Original PR description
The PR https://github.com/odoo/enterprise/pull/111833 handled the specific case when the tracker data is missing from the EasyPost response, however in certain cases `tracker` key exists, but it has a `None` value, which leads to a traceback when trying to access the stock move:
```
File "/home/odoo/src/enterprise/18.0/delivery_easypost/models/easypost_request.py", line 392, in get_tracking_link
public_url = shipment.get('tracker', {}).get('public_url')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'get'
```
This commit provides a fallback to avoid getting the error from the side of the user.
opw-6270242
Forward-Port-Of: odoo/enterprise#119400Popover content now looks more consistent and easier to use in dark mode. Secondary buttons are more clearly visible as actions, and forms inside popovers better match the surrounding popover styling.
Original PR description
Before this commit, content like form & secondary button rendered inside popovers had inconsistent styling in dark mode: - secondary buttons did not stand out properly from the popover background, making them look like plain text blocks rather than actionable buttons; - forms rendered inside popovers (such as the multi-create popover) kept their default background, which visually clashed with the popover background. This commit fixes these issues by: - adding dedicated secondary button background colors for popovers, including hover state; - aligning form backgrounds inside popovers with the popover background. task-6249985 Forward-Port-Of: odoo/enterprise#121631
Marketing Automation now shows the correct reason when a campaign activity is cancelled because a record no longer matches the campaign filter. This prevents users from seeing a misleading “Record deleted” message when the underlying customer or lead record still exists.
Original PR description
`sync_participants` calls `action_set_unlink` on every participant whose record is no longer in the campaign domain, and `action_set_unlink` writes "Record deleted" on each scheduled trace. The…
`sync_participants` calls `action_set_unlink` on every participant whose record is no longer in the campaign domain, and `action_set_unlink` writes "Record deleted" on each scheduled trace. The removed bucket also contains records that still exist but no longer match the campaign filter, so the cancelled trace dialog shows "Record deleted" even when the record was only filtered out. In `sync_participants`, the to_remove participants are split between those whose record still exists in the database (filtered out by the campaign domain) and those whose record was actually deleted. `action_set_unlink` accepts an optional `trace_message` argument, defaulting to "Record deleted", and the filtered-out batch passes "Record no longer matches campaign filter" so the cancelled trace dialog reflects the real cause. Steps to reproduce: 1. Install Marketing Automation and CRM. 2. Open Marketing Automation, create a campaign on Lead with filter Stage = New. 3. Add a begin activity to the workflow. 4. Open CRM, create a Lead in the New stage. 5. Back in the campaign, click Generate Participants. 6. In the CRM pipeline, drag the Lead from New to Qualified. 7. Back in the campaign, click Generate Participants again. 8. Open the Participants smart button, click the participant for the moved Lead. 9. Click the cancelled activity in the workflow timeline. => The activity dialog shows "Error message: Record deleted" although the Lead still exists. Ticket [link](https://www.odoo.com/odoo/project/49/tasks/6251264) opw-6251264 Forward-Port-Of: odoo/enterprise#118692
This fix ensures the Frontdesk app includes the needed scheduling component for its timeline-style planning view. It prevents missing dependency issues so users can access the view without installation or loading errors.
Original PR description
runbot-237869
The POS now shows longpolling as the default IoT connection type instead of WebRTC. This avoids misleading users when their IoT setup does not support WebRTC, while still allowing WebRTC to appear once it is actually used.
Original PR description
Before this commit, the connection status for the IoT HTTP service was defaulting to "webrtc", at least until the first IoT call is made. This would lead to WebRTC being shown as the connection type in the POS even when using a new IoT image that doesn't support it. After this commit, we use "longpolling" as the default status, which is supported by all IoT images. If WebRTC is being used, that status will be set after the first action is performed. task-6366366 Forward-Port-Of: odoo/enterprise#123445
This update preserves the expected behavior of file navigation in Knowledge after a Chrome browser change. It prevents a minor compatibility issue where scrolling actions could return a different result than before, helping keep the user experience stable.
Original PR description
Since Chrome 150, scrolling methods like `scrollIntoView()` return a Promise instead of `undefined`. This commit adds block braces to ensure the action returns `undefined` and keeps the same behavior as before. Reference: - https://chromestatus.com/feature/5082138340491264 - https://chromium.googlesource.com/chromium/src/+/50f3e3d0a9bc02aad8b8161dbdd59046991dd2c7 runbot-941309 Forward-Port-Of: odoo/enterprise#123231 Forward-Port-Of: odoo/enterprise#123031
The French Intrastat export warning links now open only the journal entries related to missing required values. This helps users quickly find and correct the affected records instead of sorting through unrelated entries.
Original PR description
Steps to reproduce: 1. Have a French company with intrastat report module installed 2. Create and validate a bill to another EU country, without filling out at least one of the required intrastat fields 3. Go to the intrastat report, and export it as XML DEBWEB2 4. In the export wizard, click on the internal links on the warning messages Issues: 1. In the Intrastat report in French localization, when there are missing values detected in the export, the Export Wizard shows internal links that lead to every journal entries - instead of showing only the relevant entries. The warning banner on the report uses the action action_invalid_code_moves which has a domain to limit what is shown on the view form. However in the method _fill_value_errors there was no domain. opw-6215339 Forward-Port-Of: odoo/enterprise#117997
Grid views grouped by a selection field now show the readable label in the list title when users open a cell's details. This avoids exposing internal technical values and makes the screen clearer for end users.
Original PR description
When grouping a grid view by a selection field and clicking on the cell magnifier, the list title showed the technical name (e.g. non_billable) instead of the display name (e.g. "Non Billable"). This commit adds a condition specifically for selection fields, ensuring that their display names are used. task-5980035 Forward-Port-Of: odoo/enterprise#122303 Forward-Port-Of: odoo/enterprise#120894
Opening the restriction fields on appointment slots no longer causes an error. This fixes a broken form interaction so users can manage appointment slot restrictions without interruption.
Original PR description
Clicking the "Restrict to User" or "Restrict to Resources" field on a slot crashed with:
invalid input syntax for type integer: "appointment_type_id.staff_user_ids"
The field domain was a quoted string instead of a list, so it was passed through as a literal value. Remove the domain: it never filtered anything and only broke the form.
opw-6349497
Forward-Port-Of: odoo/enterprise#122651Pakistan’s currency symbol (PKR) is now shown before the amount instead of after it. This makes currency formatting match common market practice and improves the clarity of displayed amounts for users in Pakistan.
Original PR description
This commit updates the symbol position of Pakistan's currency (PKR) to `before amount`, as previously it was displayed `after amount`, which is not the market practice; as shown over [here](https://drive.google.com/file/d/14pcqXTZSR0BygBXGvgQ6oCLRW0-4dYUh/view?usp=drive_link). This is a backport of [PR](https://github.com/odoo/odoo/pull/269204) task-6236452 Forward-Port-Of: odoo/odoo#271499
The Project smart button on sales orders now works even when the order has no order lines. This fixes a situation where a linked project was visible but clicking it did nothing, making it easier for users to access the related project directly.
Original PR description
Steps to reproduce: - - Create a sale order. - Link a project using the Project field. - Confirm the sale order. - Click on the Project smart button. Issue: - The Project smart button is displayed since the sale order has a linked project. However, clicking on it does nothing. Cause: - A sale order without order lines can still have projects linked through the project_id field. The action should not assume that no order lines means there are no projects to display. Solution: - Remove the unnecessary order line check and allow the existing logic to open the linked projects. task-6209658 Forward-Port-Of: odoo/odoo#270752
This change fixes an unreliable automated test in the messaging app. The test now matches how the product really works, so it should stop failing randomly and give more dependable results for future updates.
Original PR description
The `bus subscription is refreshed when channel is joined` test is sometimes failing. This test doesn't make sense: it opens the command palette and wait for a subscription to be made. However, a subscription is only done when needed (opening the thread or being a member of the channel). The step was satisfied by luck. This commit fixes the test to reflect production code: the subscription is made once the channel is opened. runbot-941462 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#274741
The print button on customer invoices is changed back to its original primary style. This reduces confusion and keeps the button appearance consistent unless the invoice has already been sent, where the secondary style still applies.
Original PR description
In task-6269645, the print button on customer invoices was set to secondary instead of primary. This is a mistake and it's confusing, so it's being reverted in this commit because it only needs to be secondary if the move is sent. task-6357618 Forward-Port-Of: odoo/odoo#273953
This update changes the website title snippet so its text alignment can be adjusted directly in the editor. It removes a styling limitation that previously blocked users from changing alignment, making layout edits easier and more flexible.
Original PR description
`s_title_form` comes with the `text-center` utility class which forbids edition through the web_editor, it needs to use inline-style instead. task-6149380 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263334
This change updates a system setting so the payment proxy uses demo values instead of test values. It helps keep the environment consistent with the intended setup and avoids mismatched configuration for current users.
Original PR description
The system parameter is already brought to demo in account_peppol module. But the current users are not for pdp. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272462
This update fixes a flaky automated test in the Discuss full flow by making the scheduled activity dates consistent in every time zone. It matters because it prevents random test failures and helps keep the messaging activity counter working reliably during validation.
Original PR description
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so…
The avatar card tour asserts the systray activity counter, which only counts activities whose state is today or overdue. The test scheduled its activities without an explicit deadline, so activity_schedule fell back to context_today on the class environment, whose superuser has tz Europe/Brussels with demo data. When the test runs between 22:00 and 00:00 UTC, that deadline is tomorrow from a UTC point of view. The state of an activity is however computed in the timezone of its assigned user, and hr_user is created without one, falling back to the server date (UTC). Its activities were therefore planned instead of today, the counter stayed empty and the tour timed out. The admin iteration kept passing because demo data gives admin the same Brussels timezone as the environment that computed the deadline, which is why only half the runs failed (both occurrences at 23:56 and 23:31 UTC). Schedule the activities with a deadline one week in the past instead: an old deadline is overdue in every timezone, whatever timezone the scheduling environment or the assigned user has, making the counter deterministic at any time of the day. https://runbot.odoo.com/odoo/error/941407 Forward-Port-Of: odoo/odoo#274679
This update resolves an issue where deleting a field in a model caused an access error, even if the model wasn't directly linked to the website. The fix ensures the search for used website forms is performed with elevated permissions, preventing the error.
Original PR description
# How to reproduce - Install the Website module - Install another module that has atleast one model with one html field, sanitize=Flase or sanitize_form=False and groups - Remove the field's group…
# How to reproduce - Install the Website module - Install another module that has atleast one model with one html field, sanitize=Flase or sanitize_form=False and groups - Remove the field's group from the current user - Enable dev mode - Go to Settings > Technical > Database Structure > Models - Pick any model (e.g. sale.order.line) - Add a field to that model & Save - Delete the added field & Save > Note : Significantly harder to reproduce since : https://github.com/odoo/odoo/commit/9a336bbb94b0a4266d84f7554c024c3abd2d1e7c I am not sure a field as mentionned in the steps exists # The problem An access error is raised for the module wich access rights were removed, even if the module is not linked in any way with the picked model # Cause of the issue Deleting the field will endup calling the `unlink()` method of `BaseModel` on the `ir.model.fields` record. This function triggers all `@api.delete` methods defined on the model : https://github.com/odoo/odoo/blob/5538132d9d14c4cc5031fc50ac0388ad2ab0fc92/odoo/models.py#L4548-L4552 This will call the this method : https://github.com/odoo/odoo/blob/5538132d9d14c4cc5031fc50ac0388ad2ab0fc92/addons/website/models/website_form.py#L153-L154 That was introduced by : https://github.com/odoo/odoo/commit/c0a827519844ec43537e4487f6abe358bb82ba9a Which prevents a field from being deleted if it is actively used in any website form. But this method does a search on every model return by `_get_html_fields` which may contains models that are not accessible by the user, so we get an access error. # Proposed solution Since `_check_if_used_in_website_form` should perform the same independently from the user, we can do the search in sudo opw-6231951 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274332 Forward-Port-Of: odoo/odoo#265781
This update corrects a display issue in the journal entry preview. Previously, omitting currency information resulted in incorrect amounts being shown in both the credit and debit columns. Now, the preview accurately reflects the credit value, ensuring consistent and reliable financial reporting.
Original PR description
In _move_dict_to_preview_vals(), when no currency is provided, the credit column falls back to the line's debit value, so any caller omitting currency_id would show the debit amount in both columns of the journal entry preview. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274594 Forward-Port-Of: odoo/odoo#269335