Thursday, October 2, 2025
29 changes · saas-18.3
Enhancements to existing features
This update improves how Point of Sale orders handle taxes, fiscal positions, product configuration, receipts, and customer display information. It helps make checkout totals and order details more consistent across related POS flows such as restaurant bills, events, loyalty, sales, and self-ordering.
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
This update improves Point of Sale behavior across several localization and payment areas, including certified scale display, Italian fiscal documents, Belgian blackbox flows, and settling due amounts. These changes help stores meet local compliance requirements and provide smoother checkout/payment handling.
Approved leave that uses a work leave type will no longer automatically create a timesheet entry. This keeps timesheet records cleaner and avoids extra entries for time off that should not be tracked as worked time.
Original PR description
When a leave using a work leave type is approved, now it should not create a timesheet. task-5097482 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229568 Forward-Port-Of: odoo/odoo#229300
The country state search field no longer shows extra spacing that made it look different from similar selection fields. This creates a more consistent and polished form experience for users.
Original PR description
There is a 2% margin added when searching for country states Remove this margin to have the field look like the majority of `many2one` fields task-5123126 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
The mobile dashboard favorite star now updates immediately when tapped, instead of appearing stuck until the user taps elsewhere. This makes saving or removing favorite dashboards clearer and consistent with the rest of Odoo.
Original PR description
The star icon on mobile would have a strange behaviour. After clicking it, the star would not change between filler/not filled until clicking elsewhere. It turns out that on mobile, after a click the hover rule is applied. And our hover rule would modify the icon to be the opposite of what it should be. This commit changes the CSS to use the same css as `BooleanFavoriteField` to stay consistent with the rest of Odoo. Task: [5092945](https://www.odoo.com/odoo/2328/tasks/5092945) 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#227663
The fleet vehicle kanban view now opens or handles vehicle contracts correctly from its contract button. This removes a small usability issue for fleet managers who need quick access to contract information from vehicle cards.
Original PR description
Fix contracts button in vehicle kanban Task-5109335 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#228341
This fixes a display issue where custom text fields added to sales order lines did not show tooltips when users hovered over them. The change restores the expected tooltip text, making customized sales order views easier to read and use.
Original PR description
## Versions 18.0+ ## Issue No tooltip can be displayed on Sale Order Lines. ## Steps to reproduce *Install Studio* - Open any SO; - Open Studio: - Click "Edit List view" on the Order Lines table; - Add a "Text" field in the columns; - Close Studio. - Add a product line if none: - Write something in the new column added with Studio; - Hover that cell and see no tooltip appear ## Cause https://github.com/odoo/odoo/blob/4daf4824a70ef679f65d5cbb15d71bc55c1e760e/addons/web/static/src/views/list/list_renderer.xml#L250 The template calls `getCellTitle` which returns a formatted text but has been overridden. These methods call the original `getCellTitle` method but don't return the formatted value. opw-4921113 Forward-Port-Of: odoo/odoo#225550
A test for settling customer dues in Point of Sale now uses the current order number instead of a fixed, date-sensitive value. This prevents false build failures when tests run in different time contexts, improving release reliability without changing user-facing behavior.
Original PR description
test was failing because the order name was hardcoded to "TSJ/2025/00001". This value includes a date-dependent year and sequence number, which vary based on context_today. this will ensure that the tour dynamically generates the order name based on the current year, making it correct for faketime builds build_error-230717 <img width="1366" height="768" alt="image" src="https://github.com/user-attachments/assets/9822763c-9c78-4589-a72a-8ac207c009d7" />
This fix makes automated tests run consistently whether or not demo data is installed. It reduces the risk of false test failures caused by default user permissions being expanded during demo setup, helping teams validate changes with greater confidence.
Original PR description
The tests should not be impacted by the demo data however it is currently the case. Indeed, a lot of groups are added to the default group user when installing the demo data. Instead, we only take the user group like it is the case when no demo is installed.
Odoo Mail no longer crashes when a new message arrives while the browser tab is out of focus. This keeps messaging stable and avoids interruptions when the system checks whether a message has already been seen.
Original PR description
Backport of #213607. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#229504
Recurring subscription invoicing now skips subscriptions linked to archived companies. This prevents customers from being billed while their company record is inactive, reducing incorrect invoices and follow-up corrections.
Original PR description
## Issue: When a company with active subscriptions is archived, the recurring invoicing cron still processes these subscriptions. Subscriptions for archived companies must not be invoiced. ## Steps to reproduce: 1. Create a company A. 2. Create a subscription for company A with next invoice date <= today. 3. Archive the company. 4. Run the scheduled action "Sale Subscription: generate recurring invoices and payments". 5. Unarchive the company and check the subscription. It should not have been invoiced. (Adjust the user's Allowed Companies if needed to access it.) backport-of: a93e7ec opw-4904325 Forward-Port-Of: odoo/enterprise#95408
This fixes an issue where changing followers on multiple records at once could incorrectly leave some followers subscribed or unsubscribed. The mail module now handles removals after processing the full batch, making follower updates more reliable for users working with multiple records.
Original PR description
When updating `message_partner_ids` on a batch of records, the previous implementation of the inverse method could lead to incorrect results if the new value implied unsubscription. The `message_unsubscribe()` method, called inside the loop over the records, unlinks `mail.followers`. This `unlink` operation invalidates all the fields cache. As a result, when processing the next record in the batch, its cached fields (the new value of `message_follower_ids`) were erased, causing the logic to fail. This commit fixes the issue by postponing all unsubscription operations. opw-5050023 Forward-Port-Of: odoo/odoo#227499
This update adjusts automated tests so they no longer depend on demo/default user group settings. It helps ensure Helpdesk timesheet and Swiss payroll checks run consistently across different test environments, reducing false failures without changing customer-facing behavior.
Original PR description
The community counter part makes the tests independent from `env['res.users']._default_groups()`. `helpdesk.group_helpdesk_manager` is the only group that is given to `base.default_user_group` in the master data (is that normal?), so we need to give it explicitly in the tests since we don't rely on the default user groups anymore in tests
This fixes an issue in the website/page editor where the color picker closed unexpectedly while previewing background colors on table cells. Users can now choose table cell background colors without interruption, making table formatting smoother and more reliable.
Original PR description
Problem: When applying a background color to a `td`, the color picker dismisses unexpectedly. Cause: After c810b0c17b2f882b0ab5d073ba38464bffb0617e, we rely on the class `o_selected_td` to check if…
Problem: When applying a background color to a `td`, the color picker dismisses unexpectedly. Cause: After c810b0c17b2f882b0ab5d073ba38464bffb0617e, we rely on the class `o_selected_td` to check if we are in a selected `td` to keep the toolbar open. However, in another fix (254efd86cd1ce871807fdc25479ebc5beeb4eab3), we removed that class during the color preview operation. Previewing a color on a `td` triggers a selection change, which runs `shouldBeVisible`. Since `o_selected_td` is not found, the toolbar closes along with the color picker. Solution: Update https://github.com/odoo-dev/odoo/commit/254efd86cd1ce871807fdc25479ebc5beeb4eab3. A better fix is to use `o_selected_td_bg_color_preview` which will undo the `box-shadow` when we preview a color. Steps to reproduce: 1. Add a table. 2. Select a cell. 3. Apply a background color. 4. Select the cell again. 5. Hover a color to preview. → The color picker dismisses once a color is hovered. opw-5066309 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#225827
This fixes an issue where increasing the quantity on a sales order using a customized warehouse route could create an incorrect extra delivery quantity. Businesses using multi-step deliveries and custom internal routes will now get the right remaining quantity to pick and ship, reducing fulfillment errors.
Original PR description
**Steps to reproduce:** - enable multi-step routes setting. - navigate to warehouse management/locations create a new location (the "test location"). - select "internal location" for the location…
**Steps to reproduce:** - enable multi-step routes setting. - navigate to warehouse management/locations create a new location (the "test location"). - select "internal location" for the location type. - select WH for the parent location - navigate to warehouse management/warehouses and select the warehouse corresponding to WH. - set the warehouse in 3 steps delivery. - click on the routes smart button. - click on the "deliver in 3 steps (pick+pack+ship)" route. - add a rule, for the action select "push to", for the operation type select "internal transfers", for the source location select the "test location" you just created and for destination location select "WH/Output". - save. - create a storable product and set an on-hand quantity - create a new sale order for 1 quantity of this product and confirm it - click on the picking smart button, change the destination location to the test location and validate - open the sale order and change the quantity to 3 **Current behavior:** A new picking is created from stock to packing zone (which is the expected behavior) but the quantity is 1 **Expected behavior:** The quantity should be 2. If we only increase the quantity by 1 on the sale order it does not even create the new picking **Cause of the issue:** The warehouse_id field is invisible in stock.rule form view when the action is push. Therefore, the rule is created without a warehouse_id. Also, moves created from a rule have the same warehouse_id as the rule. https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/stock/models/stock_rule.py#L275 So, when we validated our first move (from stock to the test location), this created a second move (from test location to output) that does not have a warehouse id (because it was created from our own push rule that we created). When we update the quantity of the sale ordre line, _action_launch_stock_rule calls _get_quantity_procurement to compute the current quantity on the moves. This method then calls _get_outgoing_incoming_moves to get the initial move created from the rule. In this case this should return only the first move created. But because the second move does not have a warehouse_id, it's rule.id is added to triggering_rule_ids. https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/sale_stock/models/sale_order_line.py#L315-L317 And the move is later added to the outgoing moves that will be returned. https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/sale_stock/models/sale_order_line.py#L322-L329 So the two moves are returned and the sum of the quantities of the moves is 2 instead of 1. https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/sale_stock/models/sale_order_line.py#L292-L294 So the product quantity for the procurement will be 1 (3-2) instead of 2 (3-1). https://github.com/odoo/odoo/blob/a729578afb7fed79aac2d622aae4da4c0917f8e5/addons/sale_stock/models/sale_order_line.py#L386 opw-5039249 Forward-Port-Of: odoo/odoo#228812 Forward-Port-Of: odoo/odoo#227421
Inventory revaluation calculations now keep full precision until the final result is ready. This prevents small rounding differences from accumulating into incorrect or negative valuation amounts, improving the reliability of stock accounting.
Original PR description
Before this commit, the remaining_value_unit_cost was rounded before any computation. In the case where the numer of layers with remaining value and remaining quantity increase, the rounding error introduced by that rounding quickly explodes, leading to a negative remaining_value during revaluation computation. After this commit, the remaining value is rounded at the end, after the computations and the checks. This ensures that the rounding error remains constant and does not accumulate over the execution of the method. opw-4901966 Forward-Port-Of: odoo/odoo#228767 Forward-Port-Of: odoo/odoo#222690
The automated guided test for the accountant merge wizard now waits for the final step to complete before closing. This reduces false failures in validation runs and helps keep accounting-related releases more stable.
Original PR description
The last check of the tour is always true. So it sometimes closes too early. Wait really for the last operation for the last check runbot-error-108440 Forward-Port-Of: odoo/enterprise#95991
Uploaded file fields added to field service worksheet templates now appear correctly in the customer-facing worksheet report. This ensures customers and staff can see attached files during report review and signing, avoiding missing information in the portal.
Original PR description
Steps to reproduce: ------- - Install industry_fsm_report module - Open FSM app - Select worksheets from settings in the configuration - Go to worksheet templates in the configuration - Create a worksheet template - Click the design template button. You arrive in the studio - Add file field and close it - Create a new task and select a newly created template in the worksheet template - Click the worksheet button in the control panel - Upload a file and save it - Click on the sign report button - Here file field is not visible Issue: ------- The file field is not visible in the worksheet portal. Cause: ------ The view of the file field is not created for the worksheet portal. Solution: ------- Created the view of the file field to display in the worksheet portal. task-3691529 Forward-Port-Of: odoo/enterprise#95754 Forward-Port-Of: odoo/enterprise#56035
A Spanish tax reporting component now handles missing date information safely instead of stopping with an error. This improves reliability during automated checks and record creation without changing normal report validation when dates are provided.
Original PR description
The `_get_mod_period_and_year` method assumed that `options['date']` would always be present with `date_from` and `date_to`. However, during the automatic `TestEveryModel.test_computed_fields_without_dependencies`, this method is called on a `new()` record where no options are provided. This resulted in a `KeyError: 'date'`. We now gracefully handle missing or incomplete `options` by returning `(None, None)` instead of raising an exception. This ensures that tests and new records can be created without errors, while preserving the original validation logic when valid options are given. build_error-231511 Forward-Port-Of: odoo/enterprise#94154
This fix prevents the Time Off calendar from mixing up user records with employee records when opened from user preferences. It helps avoid incorrect employee lookups and keeps the time off view working reliably in that navigation path.
Original PR description
Since the active model in the time off view can be res.users when we come from the user preferences, we need to check that the context model is the correct one before using the active_id, otherwise we'll try to fetch an employee with the id of the user. This has been introduced in recent fix: https://github.com/odoo/odoo/commit/c82c4a0f2674b117cdc2b0d35fe4393b8f35285a --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Self-order purchases paid online now reach the preparation display before any cashier-side print confirmation is handled. This prevents kitchen or preparation teams from waiting on an unattended cashier popup before seeing new orders.
Original PR description
When ordering from a self order and paying online, the ticket would be printed at the cashier. If the config doesn't use any physical printer it will fallback on webprint. In this case the cashier…
When ordering from a self order and paying online, the ticket would be printed at the cashier. If the config doesn't use any physical printer it will fallback on webprint. In this case the cashier would need to print via the popup on his screen. But as we are awaiting the printing to be done, the receipt screen is not updated until the cashier has closed the popup. Steps to reproduce: ------------------- * Setup a PoS to use self order and online payment. * Make sure the PoS doesn't have any printer setup. * Setup a preparation display for the PoS. * Make sure the PoS is not a restaurant. * Open the PoS, the kiosk and the preparation display on different pages * Make an order on the kiosk and pay for it. * Go to the PoS, you should see a popup trying to print the ticket. > Observation: The preparation display is not updated until the printing popup is processed. Why the fix: ------------ To make sure the preparation display is always up to date, we send the order first to the prepartion display and then to the cashier. So that if no one is at the cashier the preparation display is still updated. opw-5111555
Published product tags now show in the eCommerce sidebar as soon as the product is published, even when variants are created dynamically. This helps shoppers find tagged products immediately and avoids missing filter options before a variant is generated.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Have an attribute which creates variants dynamically; 2. create a product with two or more dynamic attribute values; 3. add a new tag to the product; 4. publish the product to eCommerce. Issue ----- The tag doesn't show up in the side-bar until after a product variant has been created. Cause ----- The tags are searched based on `product_ids` instead of `product_template_ids`, leading to tags assigned to dynamically created product variants not showing up until a variant has been created. Solution -------- Search tags based on `product_template_ids.is_published` as well as `product_ids.is_published` (in case of `addition_product_tag_ids`). opw-4985989 Forward-Port-Of: odoo/odoo#229404 Forward-Port-Of: odoo/odoo#228544
This fix prevents signed signature requests from being deleted after completion. It helps protect completed agreements and reduces the risk of losing important signed documents.
Original PR description
backport of https://github.com/odoo/enterprise/commit/b2d32811877cdf1649095435ce16274ae96421f3 opw-5111568 Forward-Port-Of: odoo/enterprise#96025 Forward-Port-Of: odoo/enterprise#95922
Pasting over selected link text in the HTML editor now respects links that should not be removed, such as protected menu items or non-editable content. This prevents users from accidentally deleting important website navigation or protected content while editing.
Original PR description
When the label of a link is fully selected and the user pastes some text, the link is removed. It was removed even if the link was in a `contenteditable=false` or was unremovable. This commit only…
When the label of a link is fully selected and the user pastes some text, the link is removed. It was removed even if the link was in a `contenteditable=false` or was unremovable. This commit only attempts to remove the link element after checking these conditions. It also only selects the link in the `before_paste` handler, and lets the normal paste logic remove it. Steps to reproduce (after 18.4, where it was noticed): - Copy some simple text - Open website builder - Select completely the label of a menu in the header - Paste - Bug: the menu item is removed, and replaced with simple text Steps to reproduce (in 18.0 and later): - Open "To-Do" app - Add a link in the middle of a line of text - With inspector, edit html to put `contenteditable="false"` on the container of the line, and `contenteditable="true"` on the link - Select completely the label of the link in the document - Paste some text - Bug: the link is removed, and the clipboard content is inserted after the non editable element task-5110141 Forward-Port-Of: odoo/odoo#228223
Fixed an issue that could affect return period reporting when reports include sections. This helps ensure the correct report section is recognized, reducing the risk of incorrect options or results in accounting reports.
Original PR description
The _init_options_return_periodicity would compare the report_id with self.id, which would lead to bugs in the case of reports with sections since in those cases it's the section id that's taken into account. Added that check. Also backported https://github.com/odoo/enterprise/pull/93187 's fix.
This update narrows an automated click-and-collect test so it focuses on confirming public access works correctly. It reduces inconsistent test behavior caused by overly fast simulated actions, helping keep quality checks stable without changing the customer-facing shopping flow.
Original PR description
Tours are too fast for imitating the user actions that led to sometimes creating 2 orders in parallel instead of reusing the first created. The test was added for b395f984b13eb83310024b9fa94d7822211ef8c1 fix, so with this commit, we keep the test more specific to the fix and avoid inconsistent behavior. Forward-Port-Of: odoo/odoo#229440 Forward-Port-Of: odoo/odoo#218417
This fix makes Chilean bank reference data load using a stable country identifier instead of matching the country by name. This prevents installation or upgrade failures when the country name has been customized or corrupted in a database.
Original PR description
`res.country` records are `noupdate` by default, which means that changes such as the following are not reverted: ```SQL pied@(none):pied_3131231> SELECT c.name->>'en_US' FROM res_country c JOIN…
`res.country` records are `noupdate` by default, which means that changes such as the following are not reverted:
```SQL
pied@(none):pied_3131231> SELECT c.name->>'en_US' FROM res_country c JOIN ir_model_data d ON d.res_id = c.id AND d.model = 'res.country' AND d.module = 'base' AND d.name IN ('cl', 'co')
+----------+
| ?column? |
|----------|
| COLOMBIA |
| Colombia |
+----------+
```
Note: in this specific, the change is clearly an error introduced in the data. Still, the error it produces (which follows) can be avoided by referring to the xmlid, instead of the record name.
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-18.4/odoo/service/server.py", line 1410, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'])
File "<decorator-gen-6>", line 2, in new
File "/home/odoo/src/odoo/saas-18.4/odoo/tools/func.py", line 89, in locked
return func(inst, *args, **kwargs)
File "/home/odoo/src/odoo/saas-18.4/odoo/orm/registry.py", line 175, in new
load_modules(
File "/home/odoo/src/odoo/saas-18.4/odoo/modules/loading.py", line 455, in load_modules
load_module_graph(
File "/home/odoo/src/odoo/saas-18.4/odoo/modules/loading.py", line 226, in load_module_graph
load_data(env, idref, 'update', kind='data', package=package)
File "/home/odoo/src/odoo/saas-18.4/odoo/modules/loading.py", line 79, in load_data
tools.convert_file(env, package.name, filename, idref, mode, noupdate, kind)
File "/home/odoo/src/odoo/saas-18.4/odoo/tools/convert.py", line 624, in convert_file
convert_csv_import(env, module, pathname, fp.read(), idref, mode, noupdate)
File "/home/odoo/src/odoo/saas-18.4/odoo/tools/convert.py", line 680, in convert_csv_import
raise Exception(env._(
Exception: Module loading l10n_cl failed: file l10n_cl/data/res.bank.csv could not be processed:
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
No matching record found for name 'Chile' in field 'Country'
```
upg-3131231
Forward-Port-Of: odoo/odoo#229218Website image galleries now load the correct gallery template when visitors click images, including on job pages. This prevents a disruptive error message and keeps browsing content smooth for site visitors and editors.
Original PR description
Clicking on an image gallery snippet currently triggers a "missing template" error. This happens because the gallery template is only defined in the 000 version file, while the corresponding view record for that version has been disabled. This commit resolves the issue by moving the gallery templates to the 001 version file, ensuring they are properly loaded. Steps to reproduce: 1. In Website, navigate to /jobs. 2. Create a new job and save it. 3. Click on any image at the end of the job page. 4. Observe the "missing template" error. Forward-Port-Of: odoo/odoo#226333
The Spanish Modelo 303 VAT return now ignores unrelated tax tags when preparing closing entries. This helps prevent incorrect VAT closing amounts and improves the reliability of Spanish tax reporting.
Original PR description
Before this commit the domain of the modelo 303 would take into account irrelevant tax_tags, causing the closing entry to be incorrect. Fixed this by adding an additional domain to the _get_vat_closing_entry_additional_domain function.