Wednesday, August 19, 2026
23 changes · saas-19.2
Enhancements to existing features
The Dutch payroll module now includes the 2026 resident income tax rate values. This helps payroll calculations stay aligned with upcoming Netherlands tax requirements.
Original PR description
Added 2026 values for the residents' income tax rates rule parameter. task-6462877 Forward-Port-Of: odoo/enterprise#127556
This update adds automated tests for the Mollie payment option in Point of Sale, covering both the backend and the POS interface. It helps catch issues earlier and reduces the risk of payment-related regressions affecting customers.
Original PR description
This commit adds both Python and JS unit tests for the Mollie POS payment method. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282024 Forward-Port-Of: odoo/odoo#281742
The IoT box update schedule no longer runs on weekends. This better matches support availability and reduces the chance of updates happening when help may not be available.
Original PR description
This PR removes weekend days from dynamic update for the iot boxes. This allows to follow the support availabilities Forward-Port-Of: odoo/odoo#282780
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-
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#270749
Resolved issues and error corrections
A leftover “Request Appraisals” action that no longer worked has been removed. Users should use the existing “Launch Campaign” option to request appraisals for multiple employees, avoiding an error when starting the process.
Original PR description
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it…
#### Description of the issue/feature this PR addresses: The "Request Appraisals" server action on hr.employee calls model._create_multi_appraisals(), a method that no longer exists. Running it raises AttributeError: 'hr.employee' object has no attribute '_create_multi_appraisals'. #### Current behavior before PR: Commit 8845eb2ac29 replaced the multi-appraisal flow with hr.appraisal.campaign.wizard: it deleted _create_multi_appraisals and repointed the employee list header button to action_open_appraisal_campaign_wizard, but left the action_create_multi_appraisals record in hr_appraisal/views/hr_employee_views.xml. Its code is now the only reference to the deleted method, so the action crashes whenever it is run. #### Desired behavior after PR is merged: The dangling action is gone. Requesting appraisals for several employees at once is done with the "Launch Campaign" button already present in the Employees list view; action_open_appraisal_campaign_wizard reads active_ids when active_model is hr.employee and pre-fills the selected employees. Nothing references the removed xml id, and the record is not noupdate, so _process_end removes it from existing databases on update; no migration script is required. Verified on a 19.0 database: with the orphan record loaded, updating hr_appraisal with this change deletes it. opw-6408609 Forward-Port-Of: odoo/enterprise#125630
The returns kanban view now supports using the up and down arrow keys to move through return selections. This prevents an error that previously appeared when users pressed the down arrow, making the workflow smoother and more reliable.
Original PR description
In returns kanban view, a traceback occurs when pressing down. Fix this by adding the support for up/down keyboard navigation for returns selection. task-6281033 Forward-Port-Of: odoo/enterprise#125164
The product catalog opened from Field Service tasks now gives more space to the unit of measure column. This improves readability and aligns the Enterprise catalog view 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#127996 Forward-Port-Of: odoo/enterprise#121139
Return shipping labels created through Sendcloud now avoid printing the customer's house number twice. This makes labels clearer and helps prevent address confusion during returns.
Original PR description
Issue ----- On return labels, the house number of the origin address (so the customer) is printed twice. Steps to reproduce ----- - Setup sendcloud - Select a return service - Enable "Generate Return Label" - Create a delivery using sendcloud - Validate the delviery > The return label has the house number printed twice Cause ----- For the origin address shown on labels, Sendcloud prints both the address line and the house number. There doesn't seem to be any parsing made on the address line to extract the house number. For the WH -> Customer label, the "from" address is taken directly from the Sendcloud account's configuration. For the Customer -> WH return, we provide it in the `from_` fields of the request. Note that, when including the house number on the address line in Sendcloud, the issue is also present. ----- Ticket: opw-6405054 Forward-Port-Of: odoo/enterprise#127855 Forward-Port-Of: odoo/enterprise#126250
Invoice extraction now compares scanned IBANs with partner bank accounts after removing spaces and punctuation on both sides. This helps the system correctly identify matching bank accounts even when saved IBANs include formatting characters, reducing missed matches during invoice processing.
Original PR description
When looking for a matching IBAN, we were searching on the `acc_number` field, which can contain spaces or special characters (dots, dashes, etc). But the OCR always returns the IBAN in a sanitized format, without any space or special characters, so it should be compared against the sanitized IBAN of the partners. task-none (issue found by chance) Forward-Port-Of: odoo/enterprise#127775
Validation errors 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 the wage for employees paid on different schedules.
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)
This change makes an automated test for image uploads more reliable by allowing a little more time for the uploaded image to appear. It helps reduce random test failures during busy system conditions, supporting smoother releases without changing user-facing behavior.
Original PR description
Before this commit, this image field test sometimes failed because it could not find the image that had just been uploaded. Similarly to [1], we increase the waitFor timeout to 1s. Indeed, uploading an image can take time, and with high CPU usage, it could happen that the default 200ms delay wasn't enough. [1] https://github.com/odoo/odoo/pull/168196 runbot error-242406 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#281200
The attendance kiosk no longer loads a presence status script that is not used in that view. This reduces unnecessary resource loading and helps keep the kiosk experience lighter without changing its 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#282410
The website editor now shows dynamic snippet filter names in the user’s preferred language instead of automatically using the website language. This makes the editing experience clearer and more consistent for multilingual sites.
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#280152 Forward-Port-Of: odoo/odoo#275390
This change restores a small component definition needed by automated POS tests, preventing false failures during order-cancel flows. It does not change the customer experience, but it keeps the Point of Sale test suite reliable and unblocks builds.
Original PR description
### Issue: In 19.3, the following hoot tests fail with a RunBot error: - "called at right time (when canceling order)" - "called at right time (when canceling order never sent to blackbox)" - "called…
### Issue:
In 19.3, the following hoot tests fail with a RunBot error:
- "called at right time (when canceling order)"
- "called at right time (when canceling order never sent to blackbox)"
- "called at right time (when canceling a combo order)"
### Cause:
Commit 0dfd71b9f4 removed `close` from `ControlButtonsPopup` as the Dialog patch now handles closing via `this.data.close()` With no remaining props to declare, `static props` was removed entirely
Without `static props`, Owl skips all prop validation but emits: "Component 'ControlButtonsPopup' does not have a
static props description"
`mountWithCleanup` forces `warnIfNoStaticProps` to `true` in hoot tests, causing the tests to fail
`close` is declared as optional since `dialog_service.js` always injects it via `subProps: markRaw({ ...props, close })` at runtime, but the component no longer uses it directly
### Steps to reproduce:
- Install `l10n_be_pos_blackbox`
- Enable Developer mode
- Open the JS test UI
- Run one of the failing tests
runbot-941231
Forward-Port-Of: odoo/odoo#277790The link preview popover now gives the edit/magic wand control a larger clickable area and a hover effect, making it easier to find and use. In dark mode, the Edit button background has also been adjusted so it stands out properly against the popover.
Original PR description
According to accessibility recommendations, the magic wand icon link inside the link preview popover is too small. This commit makes it clickable on an area of 24px x 24px, and adds the missing effect to provide feedback on hover. task-6373506 Forward-Port-Of: odoo/odoo#282534 Forward-Port-Of: odoo/odoo#276929
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was mi
Original PR description
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was missing from the report template if self-billing is enabled. ***Fix*:** * Add the missing condition so that the self-billing header is displayed when **Self Billing** is enabled on the journal. * For reference, here is the [Document](https://www.gesetze-im-internet.de/ustg_1980/__14.html) link. Ticket [link](https://www.odoo.com/odoo/project.task/6281066) opw-6281066 Forward-Port-Of: odoo/odoo#282664 Forward-Port-Of: odoo/odoo#272857
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with "TypeError: this.pos.autoCourseAllocation is not a function". Cause: b86126bbfb17105323a8ac972cb5062b95325fc4 moved autoCourseAllocation and cleanAutoCourseAllocation out of ProductScreen (point_of_sale) into the PosStore patch of pos_restaurant, but kept the two call sites in point_of_sale's
Original PR description
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with…
Steps to reproduce: - Install Point of Sale without the Restaurant module - Open a session and scan the barcode of a product Issue: The product is never added to the order, the client crashes with "TypeError: this.pos.autoCourseAllocation is not a function". Cause: b86126bbfb17105323a8ac972cb5062b95325fc4 moved autoCourseAllocation and cleanAutoCourseAllocation out of ProductScreen (point_of_sale) into the PosStore patch of pos_restaurant, but kept the two call sites in point_of_sale's ProductScreen._barcodeProductAction, now routed through this.pos. Both methods therefore only exist when pos_restaurant is installed, so on a plain shop configuration the call throws. The other call site, ProductScreen.addProductToOrder, is patched in pos_restaurant itself, which is why only the barcode path is affected. Runbot installs every module, so the patch is always loaded there and the crash went unnoticed. Also restore the argument forwarding in the pos_restaurant PosOrder.removeOrderline patch introduced by the same commit: it declares deep but called super.removeOrderline(line), dropping it. PosStore.breakCombo is the only caller passing deep=false. opw-6478112 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282919
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
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
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list neve
Original PR description
Before this commit, the full composer tour can fail on the step that drops a file on the composer, waiting for a `.o-Dropzone` that never shows. This happens because the channel mention list is sometimes still open when the tour drags the file in. The composer gets no dropzone then, as a dropzone only shows when the UI active element contains its target, and the open mention list is the UI active element. The dropzone is only updated on the drag events, therefore closing the mention list never brings it back. Note that the same race is reported on saas-19.1, where the tour crashes on `dispatchEvent` of null instead, as the `dragFiles` helper there queries the dropzone once where `dropFiles` waits for it. This commit waits for the mention list to close before the drag. https://runbot.odoo.com/odoo/error/946097 Forward-Port-Of: odoo/odoo#282716
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing
Original PR description
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax…
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing the ZUGFeRD template into the Accounting tab of his contact) 4. Send it and see that the tag <ram:CategoryCode> is setted as E instead of G ### Cause of the issue: The logic assigning the 'G' and 'K' tax category codes was only triggered if the supplier was located within the EEA. If the supplier was outside the EEA, the code bypassed this block entirely and fell back to the default 'E' code for 0% taxes. ### Reason to introduce the fix: Update the condition to trigger when either the supplier or the customer is in the EEA. This ensures that cross-border transactions involving at least one EEA party correctly evaluate and apply the 'G' (Export outside the EU) category code. Also the case supplier not in eea with VAT filled in + customer in eea + RC tax with amount != 0 is fixed now (letter G reported instead of S). ### Documentation: [eInvoicing technical guidance document_v1.pdf](https://github.com/user-attachments/files/30831749/eInvoicing.technical.guidance.document_v1.pdf) opw-6407399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282497 Forward-Port-Of: odoo/odoo#281245
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is
Original PR description
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never`…
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is raised. Root cause: --- - In `_is_add_to_cart_allowed()`[1], the method calls `_get_contextual_price()` [2] to check if the product's price is zero when `prevent_zero_price_sale` is enabled. - However, `_get_contextual_price()` is called without the no-variant attribute values in the context, so it does not account for their `price_extra`. For a product with list price as 0 and attribute with extra price, the price is incorrectly computed as 0, causing `_is_add_to_cart_allowed()` to return `False`. Solution: --- - Before calling `_is_add_to_cart_allowed()`, set the product's context with the no-variant attribute values via `_get_product_price_context()`, so that `_get_contextual_price()` correctly includes the price extra in its computation. [1]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/controllers/cart.py#L117-L120 [2]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/models/product_product.py#L149-L150 opw-6365566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282705 Forward-Port-Of: odoo/odoo#278620
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 s
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#282565 Forward-Port-Of: odoo/odoo#267118