Tuesday, April 21, 2026
27 changes · 19.0
Enhancements to existing features
The website video snippet now uses a built-in SVG placeholder instead of relying on an external or maintained video preview. This reduces maintenance needs and helps keep the website editor preview reliable over time.
Original PR description
Prior to this PR, the `s_video` inner snippet was using a video as placeholder, which implied maintenance to ensure the video is always available. To avoid maintenance and ensuring long term effectiveness, we replace this video with a `SVG` placeholder, similarly to what has been done for the `s_image`. task-5441285 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Moves Analysis report now shows the date of each stock move directly in the standard list view. This makes it easier for users to review and understand inventory movements without enabling debug mode.
Original PR description
The date of the move is a basic and important information. Show it on the 'Moves Analysis' report list view, previously was only displayed in debug mode. task-5380628
The wording for the Invoicing Switch Threshold has been clarified to better explain which records are ignored. This helps users understand that all entries created by Invoicing before the threshold date are excluded, reducing confusion when switching accounting methods.
Original PR description
The previous "Invoicing Switch Threshold" explanation was misleading as it said only invoices prior to the threshold date is not taken into account. The explanation is updated to state that all entries created by Invoicing before the threshold date will be ignored. task-5940144
Resolved issues and error corrections
This fixes an issue where non-livechat conversations could be saved as active visitor live chats. Businesses using website chat will see a cleaner, more accurate active chat list for their operators.
Original PR description
Add an explicit `this.channel === "livechat"` guard so only actual livechat conversations kept in `storeAsActiveVisitorLivechats`.
Code cleanup and technical improvements
This update appears to reorganize or clean up internal test setup documentation or configuration. It has no expected direct impact on day-to-day users, but helps keep development and testing processes easier to maintain.
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
Miscellaneous changes
This update adds a simple greeting message to the Odoo 19.0 onboarding material. It is a minor wording change intended to make the product feel more welcoming, with no expected impact on business workflows.
Original PR description
Description of the issue/feature this PR addresses: This PR does not solve an issue. Current behavior before PR: Odoo 19.0, your open source business apps Desired behavior after PR is merged: Odoo 19.0, but shipped with a warm greeting. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an unstable automated test for the website/editor link popover so it behaves more like a real user click. The change helps reduce false failures in Odoo's validation pipeline without changing end-user functionality.
Original PR description
The popover opening is triggered through click, but there is a selectionchange handler on click that checks if the selection is outside of the link and, if it is, closes the popover. In this case, the click method didn't set the selection inside the link properly because of the presence of \ufeff around the link. The test actually passes by mistake when the runbot was fast, but failed when the runbot was slow, as the selectionchange handler had the time to execute and close the popover. This commit forces the selection to be inside the link after calling click, to be closer to what actually happens when a user click on a link, as opposed to a programmatic click. runbot-161423 Forward-Port-Of: odoo/odoo#259688
The Belgian localization now uses the correct exemption code and reason for the 0% S tax. This helps ensure tax documents contain accurate exemption information for compliance and reporting.
Original PR description
The tax 0% S had a wrong tax exemption code and tax exemption reason. This commit corrects it. Task-6127195
Preparation printers now include the selected attribute value when a variant is ordered as part of a combo in Point of Sale. This helps kitchen or preparation staff see the exact product choice instead of only the base product name, reducing confusion and order mistakes.
Original PR description
Before this commit, the preparation printer did not display the attribute value for an instant variant added inside a combo choice. This occurred because the attribute value was not properly set on the variant order line. Steps to reproduce: * Create a PoS product with multiple variants. * Create a combo product with a choice containing the variants. * Configure a preparation printer. * Open a PoS session and order the combo. * The printer displays only the base product name. opw-5949132 Forward-Port-Of: odoo/odoo#256981
This fix ensures that when a working schedule entry is changed from lunch to another part of the day, its stored duration is updated correctly. This prevents attendance overview errors for employees using the affected schedule.
Original PR description
Since #217895, `duration_hours` is now stored and needs to be recomputed when we change the attendance's `day_period` from lunch to morning/afternoon/full_day otherwise we will run into division by 0 in `_get_attendance_intervals_days_data`. ### Steps to reproduce 1. Change the day period of one of the working hours of a working schedule from Lunch to Morning. 2. Open the attendance overview including the attendances of an employee that has the working schedule from step 1. opw-6129881
Adds test coverage to ensure consigned inventory is excluded when calculating average cost and stock value. This helps keep product costs and inventory valuation accurate when company-owned and third-party-owned stock are stored together.
Original PR description
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco…
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco product with a cost of 10 - click on the quantities smart button and then "update quantity" to open the quants view - create one line with a quantity of 1 and no owner - create one line with a quantity of 1 and an owner outside the company **Current behavior:** problem A: open the 'stock' view and look for your product, the unit cost is 5 problem B: navigate back to the quants view of the product, unhide the value column, the value is 5 for the non consigned quant **Expected behavior:** problem A: the unit cost should be 10 (because consigned product shouldn't be taken into account when computing the unit cost) problem B: the non consigned quant value should be 10 for the same reason **Cause of the issue:** problem A: Inside _compute_value(), to compute total_value_by_company_id, we use _with_valuation_context() https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L196-L203 which excludes consigned products https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L362-L364 So when we iterate through 'products' and fetch qty_available for our product the value is going to be 1. But when computing avg_cost at the end of the method, we iterate through 'self', so we don't have this context anymore and the value of qty_available is 2. https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L271-L273 That's because qty_available is computed with _compute_quantities() which depends on context (including owner_id) https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock/models/product.py#L148-L152 problem B: when computing the value of the quant, there is no context specifying that the consigned quantities should be excluded https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock_account/models/stock_quant.py#L61-L62 opw-6049413
Employee searches in Attendance Kiosk Mode now work reliably when filtering by department. This prevents an error that could block users from manually identifying employees and recording attendance.
Original PR description
**Steps to Reproduce:**
1. Install `hr_attendance` module with demo data.
2. Go to Attendances > Kiosk Mode > Identify Manually.
3. Select any department.
4. Try searching for an employee.
**Error:**
`ValueError - not enough values to unpack (expected 3, got 1)`
**Cause:**
The `employees_infos()` controller assumes that every item in the domain is a valid triplet (field, operator, value). However, the domain may also contain logical operators ('&'), which are not triplets. And then trying to unpack such entries leads to a ValueError.
**Fix:**
Add a validation to ensure the condition is a proper triplet before unpacking. Non-conforming entries (logical operators) are skipped.
sentry-7401444075
opw-6113268
Forward-Port-Of: odoo/odoo#258825Access error messages now identify the actual rule blocking access to archived records, instead of incorrectly suggesting every rule failed or pointing to a company-related issue. This helps users and support teams understand the real reason access was denied more quickly.
Original PR description
When accessing an archived record directly, if access is prevented by a record rule other than a multi-company global rule, the error message incorrectly reports that all rules are failing, suggesting a company issue even though it is not the actual cause. The problem is that when access is denied, the diagnostic method `_get_failing` is used to determine which rules are failing. This method performs several count queries with different rule domains. However, `active_test` is True by default, excluding archived records from the count, causing the rule evaluation to miss some records and incorrectly mark rules as failing. With this commit, `_get_failing` evaluates rules with `active_test=False`, ensuring that only actually failing rules are reported. Forward-Port-Of: odoo/odoo#259592 Forward-Port-Of: odoo/odoo#259344
Attachments uploaded to cloud storage now keep the file type that was originally provided instead of having it guessed again. This helps ensure files are handled and displayed correctly after upload, reducing confusion or errors for users working with cloud-stored attachments.
Original PR description
When uploading an attachment to cloud storage via `_post_add_create(cloud_storage=True)`, the attachment's original `mimetype` is guessed even if we specify it. With this commit we explicitly preserve given mimetype Discovered during task-5153790 Forward-Port-Of: odoo/odoo#257979
This fixes an unstable automated test for the HTML editor’s icon feature. It helps keep the development and release pipeline reliable by reducing false test failures, with no expected change for end users.
Original PR description
My last desperate fix attempt did not fix the issue so here is yet another desperate fix attempt. I have seen issues related to the use of `setContent` just to set the selection in the past so I hope it might be that. It's the only noticeable change between this test and the others, be it icon tests or color selector ones. runbot-242333 Forward-Port-Of: odoo/odoo#259731 Forward-Port-Of: odoo/odoo#259544
Subcontractor resupply transfers now correctly show the related purchase order when stock is supplied using the take-from-stock-or-procure route. This improves traceability for purchasing and warehouse teams by making it easier to connect resupply operations back to the original order.
Original PR description
### Steps to reproduce: - In the settings enable: Subcontracting, Multi-Step Routes - Inventory > Configuration > Warehouse Management > Routes - Edit the 'Resupply Subcontractor on Order' route,…
### Steps to reproduce: - In the settings enable: Subcontracting, Multi-Step Routes - Inventory > Configuration > Warehouse Management > Routes - Edit the 'Resupply Subcontractor on Order' route, rules supply method to: Take from stock, if unavailable, trigger another rule (mtso) - Create a subcontracted bom For a product P with a component COMP - Create and confirm a PO for 1 unit of P with your subcontractor - Use the Resupply smart button to access the resupply picking #### > The resupply picking does not refer to the source PO ### Cause of the issue: The link is currently computed based on `move_dest_ids` which are only set for mto moves. However, moves created from mtso rules are `make_to_stock`. ### Fix: Since 19.0 2713876dbc70d3984e584a9037a2206dcda4e84a, we can rely on references to rebuild the link between the resupply picking and the source PO even in mtso. Note that this will also add the source PO link to each other picking of the reference. opw-6079680 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix makes an automated test for the HTML editor more dependable by avoiding timing assumptions that could fail on slower test servers. It does not change how users interact with the editor, but it helps keep releases stable by reducing false test failures.
Original PR description
Waiting for a full animation frame is too dangerous. In the general case, an animation frame happens every 16ms, in which case the power buttons haven't been updated yet since they have a debouncing timeout of 30ms. However, when the runbot is slow, more than 30ms may very well have elapsed between two animation frames. When that is the case, the power buttons are displayed and the test fails. This commit changes the forced awaiting of an animation frame to a waiting pased on the time passed. In the general case, an animation frame will have happened in 20ms, so the test will still catch a regression. When the runbot is slow however, more time might have passed, but not necessarily an animation frame, so the power buttons should still be invisible, making this test more reliable. runbot-242466 Forward-Port-Of: odoo/odoo#259654
This fix prevents percent signs in formatted page text from appearing doubled when no dynamic placeholders are used. It helps ensure customer-facing content, such as testimonials or translated snippets, displays exactly as written.
Original PR description
`_compile_format` unconditionally escaped `%` to `%%` to protect against Python's `%`-formatting, but only appended the `% (values,)` formatting operation when `#{...}` placeholders were present. With no placeholders, the escape was never undone and `%%` leaked into the rendered output.
This went unnoticed until the introduction of paramteric t-call: https://github.com/odoo/odoo/commit/eb6e88a25050
But since we use `.translate` and `.f` directly in existing views this became apparent
Example:
```xml
<t t-call="website.s_wd_testimonial"
_testimonial_quote.translate="...by 400%."/>
```
will be rendered as `...by 400%%.` on the page.
To prevent this, we can simply check for the absence of values and simply return the repr as is if there isn't any.This fixes purchase behavior so a supplier-specific unit of measure set for one product variant is not reused for other variants of the same product. It helps prevent incorrect purchasing quantities or units when buying similar product variants from suppliers.
Original PR description
Make sure any UoM defined on a supplierinfo having a specific variant cannot be used by other variant of the same product template Task: 6042382 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
Draft delivery orders now show products as available when on-hand stock exactly matches the requested quantity. This prevents users from seeing a false shortage warning when inventory is actually sufficient to fulfill the delivery.
Original PR description
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is…
Steps to reproduce: - Create a storable product "P1" - Update on-hand quantity to 2 units - Create a delivery with 2 units of P1 and keep it in draft state Problem: The forecast availability is displayed in red (not available), even though the stock is sufficient to fulfill the move. Explication: For draft consuming moves, the forecast availability is computed as: `virtual_available - move.product_qty` In the case where stock exactly matches the demand, this results in 0. However, on the JS side, availability is evaluated with: `forecast_availability >= product_qty` So with forecast_availability = 0 and product_qty = 2, the condition evaluates to False, incorrectly marking the move as not available. https://github.com/odoo/odoo/blob/c7fede7f44c668ccc0a094d8341c3cae8879a7f1/addons/stock/static/src/widgets/forecast_widget.js#L31 Solution: When the available quantity is sufficient to cover the move (using float_compare), set forecast_availability to the full available quantity instead of subtracting the move quantity. This ensures the JS condition correctly evaluates to True and the move is marked as available. opw-5159142 Forward-Port-Of: odoo/odoo#257670 Forward-Port-Of: odoo/odoo#257354
Invoice users can now select today's date in the currency rate date picker and have the correct rate applied. This fixes a workflow issue where choosing today's rate after another date closed the picker without updating the invoice.
Original PR description
On an invoice, using the date picker to choose the currency rate did not allow picking today's date. Steps to reproduce: - Activate a currency - Add currency rate for today, yesterday and tomorrow - Create a new invoice - Select the newly activated currency - Pick yesterday's date - Pick today's date Current behavior: picking today's date close the date picker without doing anything Expected behavior: picking today's date close the date picker and apply today's currency rate (or latest if today's doesn't exist) Cause: The date picker was opened with today's date selected, preventing selecting it again. Opening the date picker with the right date selected isn't possible as we don't save the currency rate date. It would require doing a reverse search among the currency rate date which might be wrong as the currency rate can be customized. opw-6046169
Fixes an issue where message input text could become white on a white text box when a website used a dark background theme. This makes customer replies in Helpdesk and similar website forms readable while users are typing.
Original PR description
# Setup Edit the theme of the website : in the Light & Dark section, set the first color to black. The main background color of the website should be black and the text should be in white. # How to…
# Setup Edit the theme of the website : in the Light & Dark section, set the first color to black. The main background color of the website should be black and the text should be in white. # How to reproduce - Install the Helpdesk app - Go to Website > Help - Submit a ticket (the ticket's information is not important) - Click the ticket link shown when the ticket is submitted - Start writing a message in the Communication History. # The problem As long as the text bubble is focused, the text is white even though the bubble is also white, making the text unreadable. Note : the same problem is present for product reviews in the eCommerce application. These text bubbles seems to be intended to stay white even in a dark main background color, so the text should be black : https://github.com/odoo/odoo/blob/6b21829159d3d16a0a0060e30814f9d969b44418/addons/mail/static/src/core/common/composer.scss#L103 # Cause The textarea (text bubble) has a the `.form-control` css class coming from bootstrap that applies `color: var(--bs-body-color)` : https://github.com/odoo/odoo/blob/6b21829159d3d16a0a0060e30814f9d969b44418/addons/web/static/lib/bootstrap/dist/css/bootstrap.css#L2115-L2131 In our case, it sets `color` to #FFF (I'm not 100% sure where this value is coming from since I did not find any instance where --bs-body-color or --body-color are ever set to that value). Anywyay, this value is overidden by `.o-discuss-text-body`: https://github.com/odoo/odoo/blob/6b21829159d3d16a0a0060e30814f9d969b44418/addons/mail/static/src/core/common/core.scss#L99-L101 But the value is overriden again when the textarea is focused by the `form-control:focus` css class that sets back the color to #FFF: https://github.com/odoo/odoo/blob/6b21829159d3d16a0a0060e30814f9d969b44418/addons/web/static/lib/bootstrap/dist/css/bootstrap.css#L2143-L2149 The issue was caused by this commit that changed the class used to define the color for the discuss messages : https://github.com/odoo/odoo/commit/3557de4232ebc307c8861379f6573d7b36cd8db6 Because `.o-discuss-text-body` is overriden by `form-control:focus` while `.text-body` is not. This is most probably due to the order in which the stylesheets are applied. # Proposed solution Add `, .o-discuss-text-body:focus` to make sure the rule is also applied when the text bubble is focused opw-6063961 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A test setup issue was corrected so it first confirms the needed module is installed before using its security group. This prevents avoidable test failures and helps keep invoice export validation stable for Belgian down payment scenarios.
Original PR description
The `get_default_groups` call happens during super.setUpClass(), therefore we have not checked (yet) if the module in which the security group is in is installed, and we end up with an Exception. task-none Forward-Port-Of: odoo/odoo#260230
Generating a W-2 CSV now works even when the report’s end date is left blank. If no end date is provided, the system will use the current year for the file name instead of stopping with an error. This prevents a frustrating interruption when users create payroll reports.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#113408This change updates the test invoices used for Peruvian electronic invoicing so they match the corrected unit price rounding rules. It helps keep the automated checks reliable and prevents false failures in the localization tests.
Original PR description
https://github.com/odoo/odoo/commit/e79136d04c844f9a0a8c6d0532c65e0cc3a68b8f fixes unit price rounding in peppol. This PR fixes a broken test in l10n_pe_edi opw-6009771 Forward-Port-Of: odoo/enterprise#114159
When a signed document from a project task or project is added to Documents, it now opens in the project’s configured folder instead of defaulting to My Drive. This keeps signed attachments organized consistently with regular project files and reduces manual filing.
Original PR description
Steps to Reproduce --- - Request a signature from a project task or project and complete the signing process. - In the chatter, click "Add to Documents" on the signed attachment. Issue --- Signed documents attached to projects or tasks default to "My Drive" when added to Documents, instead of using the project's configured Documents folder. Current Behaviour --- - Regular task/project attachments correctly preselect the project Documents folder. - Signed attachments fall back to "My Drive". Expected Behaviour --- Signed documents linked to projects or tasks should preselect the project's Documents folder, consistent with regular attachments. Fix --- Extend get_documents_operation_add_destination to handle sign.request attachments linked to project.task or project.project, resolving to the corresponding project Documents folder. task - 5226770
This change corrects the year shown in return names so date ranges display the actual calendar year. It prevents confusing labels like showing Jan 2022 instead of Jan 2023, which improves clarity for users reviewing reports and returns.
Original PR description
Steps to reproduce: - Create a return from Jan 2023 to April 2023 -> the dates displayed in the name will be Jan 2022 - Apr 2023 The display is incorrect because we used the wrong date format, and therefore switch from using YYYY to yyyy as the first one is the ISO standard year and the second the calendar year. They might differ on the result here because 01 Jan 2023 falls on a Sunday, but ISO week starts on Monday, so it took the previous year (2022)