Daily updates from Odoo
Tuesday, April 21, 2026
170 changes
23 changes
Resolved issues and error corrections
This change corrects how unit prices are written into Peppol invoice files so they match the calculated line total exactly. It prevents invoices from being rejected by Peppol validation when prices have many decimal places.
Original PR description
**PROBLEM** Previously, we rounded the unit price up to 6 digits in the generated xml for peppol. However, odoo compute the lineExtensionAmount with the raw unit price. The generated xml is invalid because `priceAmount*InvoicedQuantity != LineExtensionAmount`. **STEP TO REPRODUCE** 1. Create an invoice with unit price of 0.01110515964, and quantity of 278362.5. 2. Generate an XML with peppol, and try validating the invoice. You should have the following error: `[PEPPOL-EN16931-R120]-Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount` opw-6009771 Forward-Port-Of: odoo/odoo#259759 Forward-Port-Of: odoo/odoo#255358
This change removes unwanted empty lines at the beginning and end of messages before they are sent. It helps make outgoing messages look cleaner and more consistent for recipients.
Original PR description
Trim the leading and trailing empty lines in the message body before sending it to avoid unwanted empty lines at the beginning and end of messages. task-6027013 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259723 Forward-Port-Of: odoo/odoo#259136
This change updates test data for Peru electronic invoicing to match the corrected unit price rounding behavior. It helps keep the automated checks reliable so future updates do not introduce regressions in this local accounting flow.
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
The POS due settlement flow now correctly includes refund orders when calculating what a customer still owes. This ensures the amount shown and settled reflects the true net balance, preventing customers from being overcharged or under-settled.
Original PR description
Step to reproduce - install "pos_settle_due" - have a customer, A and a pos with payment method "customer Account" - start pos, add 3 qty of product with unit price 10$ with partner A - use payment method "customer Account" i.e. of type "pay_later" (do not invoice orders) - refund 1 qty of previous order using same payment method - go to partner list, notice A has 20$ as due - click on "hamburger btn" > settle due amount Observation: - notice we only get the order amount as due i.e order with 30$ - we should have received the refund order too, so that net due of 20$ can be processed Cause: - currently, we didn't considered refunds orders at all, when settling dues Fix: - now we consider order with total < 0 i.e refund orders to be included for settlement opw-5869313 Forward-Port-Of: odoo/enterprise#113950 Forward-Port-Of: odoo/enterprise#107883
This fix allows Point of Sale to sell event tickets even when a multi-slot event has unlimited availability. Previously, those tickets could incorrectly appear as sold out, preventing customers from completing their purchase.
Original PR description
**Steps to reproduce:** - Make an event, put it to announced state - Allow multi slots and create a product - Go to the pos and try to order it - "All slots are booked out for this event" appears **Why the fix:** When we set 0 as a maximum quantity for an event slot, the quantity is unlimited, in the code, the availability is set to a string "unlimited". This was not taken into account in the case of multi slots, as we only checked if the availability was a number greater than 0. As "unlimited" is not a number, we thought we didn't have any slots available and returned the error that said all slots were full. We now add the unlimited tickets to the availability list. opw-6006696 Forward-Port-Of: odoo/odoo#254220
This update prevents timesheet information from overlapping when users scroll in the attendance systray on smaller screens. It also adjusts the layout so the list and checkout button stay readable and avoids awkward double scrolling.
Original PR description
Before: The systray overlaps the records when scrolling on small screens Changes: - Expands the record list to avoid scrolling overlaps - Make the timesheet list expand before the checkout button to ensure no overlap - Restrict the height of the timesheet list to avoid the double-scrolling problem --- task: 6115674
This update corrects how invoice line amounts are exported in the Luxembourg FAIA XML file when a line has a negative unit price. It ensures debit and credit values are reported consistently, preventing validation errors during file checks and submission.
Original PR description
This is one of several commits fixing the FAIA xml export: - #113452 - #113455 - #113846 - #113720 When an invoice line has a negative `price_unit`, the `Invoice/Line/InvoiceLineAmount/Amount` element has a negative value. This causes validation errors when comparing the total debit or credit values (such as `SalesInvoices/TotalDebit`) to the individual amounts, as the sum of individual "debit" lines will include some credit amounts and vice versa. Solution: record if the line is actually a debit or a credit, then use the absolute value of the balance in the Amount element. opw-5427296 [Link](https://www.odoo.com/odoo/unassigned-tasks/5427296) Forward-Port-Of: odoo/enterprise#113606 Forward-Port-Of: odoo/enterprise#113316
The CRM onboarding tour now places the lead generation steps at the end, preventing the tour from getting stuck or looping back on itself. This makes the guided experience more reliable for users trying out lead generation in CRM.
Original PR description
The crm_iap_mine module extended the crm tour, by adding steps to introduce the lead generation feature. These steps were inserted in the middle of the tour, which caused the tour to backtrack and…
The crm_iap_mine module extended the crm tour, by adding steps to introduce the lead generation feature. These steps were inserted in the middle of the tour, which caused the tour to backtrack and loop on itself. Why? For the tour to wait for the next step, we specify the selectors it should look for. In this case, because the modal redirects to the same page (with an updated domain), we cannot specify a selector that would be unique to the new page -> the target is found before the redirect -> after the redirect happens, the tour backtracks to try and recover, causing the loop. Moving the steps to the end of the tour fixes the issue. The disadvantage of this is that no the last step of the tour is not deterministic - it can fail if the user selects a combination of countries and industries which have no valid leads (Antarctica...) or if the user doesn't have enough IAP credits. In this case, the 'Congrats' rainbowman is shown even if the generation failed. Task-5386684 Forward-Port-Of: odoo/odoo#259960 Forward-Port-Of: odoo/odoo#249733
This update replaces the removed payslip line editing wizard with direct, inline payroll computation. It keeps payroll adjustments working smoothly while reducing the chance of interruption for users managing payslips.
Original PR description
We replace the previously removed payslip line edition wizard with inline payslip computation
Belgian Intervat settings are now shown not only for companies based in Belgium, but also for companies that use Belgian taxes through a Belgian fiscal position. This means users can review, change, or disable Intervat configuration even when the company itself is not registered in Belgium.
Original PR description
### Issue: When demo data is disabled, creating a Belgian fiscal position installs the Belgian taxes and enables BE accounting Starting from 19.0, Intervat redirection is enabled automatically, but the Intervat settings are not available because the company itself is not Belgian As a result, the Intervat configuration cannot be changed or disabled ### Cause: The Intervat settings were only shown when the company country was Belgium However, companies using Belgian taxes through `account_enabled_tax_country_ids` must also be considered ### Steps to reproduce: - Disable demo data and install `accountant` - Create a Fiscal Position "Belgium" (Country: Belgium, Foreign Tax ID: BE010203040) - Click the alert to install the Belgian taxes - Open Settings Before the fix: The Intervat settings are not available opw-6068480 Forward-Port-Of: odoo/enterprise#112609
This change prevents an error that could appear when a user tries to confirm a scrap after first dismissing the insufficient quantity warning. It ensures the system only removes the related scrap record in the right flow, so users can safely continue without seeing a traceback.
Original PR description
**Version:** --------- - saas-19.2+ **Steps to reproduce:** ------------------------ * Install the *Inventory (stock)* module. * Create a *storable product* with tracking enabled. * Update the…
**Version:** --------- - saas-19.2+ **Steps to reproduce:** ------------------------ * Install the *Inventory (stock)* module. * Create a *storable product* with tracking enabled. * Update the on-hand quantity to *5 units*. * Navigate to *Inventory > Operations > Scrap* and create a new scrap record. * Select the created product and set a quantity *greater than the available on-hand quantity (e.g. 6)*. * Click on *Confirm*. * An *insufficient quantity* wizard opens. * Click on *Discard*. * Then click again on *Confirm* in the wizard. **Issue:** --------- * A traceback occurs with the following error: `ValueError: Expected singleton: stock.move()` **Cause:** ---------- * When clicking *Confirm*, button the insufficient quantity wizard is opened with a `scrap_move_id`. https://github.com/odoo/odoo/blob/3206cd9bc0af33b047138fc6666a14f8d11da785/addons/stock/models/stock_move.py#L2747 https://github.com/odoo/odoo/blob/3206cd9bc0af33b047138fc6666a14f8d11da785/addons/stock/models/stock_move.py#L2742 * Clicking *Discard* button triggers `action_cancel`, which unlinks the associated `scrap_move_id`. https://github.com/odoo/odoo/blob/3206cd9bc0af33b047138fc6666a14f8d11da785/addons/stock/wizard/stock_warn_insufficient_qty.py#L48-L49 * However, the wizard remains open, and clicking *Confirm* again triggers `action_done`, which calls: https://github.com/odoo/odoo/blob/3206cd9bc0af33b047138fc6666a14f8d11da785/addons/stock/wizard/stock_warn_insufficient_qty.py#L46 * At this point, `scrap_move_id` no longer exists, leading to the singleton error. - Before saas-19.2 This behavior was previously handled in: https://github.com/odoo/odoo/commit/c361c3778ef4755b4760039a4fd8f9ed88294b64 Later in this commit https://github.com/odoo/odoo/commit/1c7d80a10b5d7db1c4163166bf52b3f3c77044ba the condition was removed during refactoring, causing the scrap move is to be unlinked in all flows. **Fix:** ------ * Add a context key to ensure that the scrap move is only unlinked during the `action_scrap` flow, preventing access to a deleted `scrap_move_id`. --- opw-6128188 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update removes the hover tooltip that appeared for boolean fields in calendar popups. It prevents confusing or unhelpful content from showing when users move their mouse over these fields.
Original PR description
Before this commit, the tooltip of a boolean field in calendar popover shows html content when the user hovers the boolean field. This commit removes the tooltip of boolean field in calendar popover since the information inside that tooltip is not really useful for the user. Issue found during the development of task-5994205 Forward-Port-Of: odoo/odoo#259529 Forward-Port-Of: odoo/odoo#259011
The digest now counts connected users based on the companies they are allowed to access, instead of only their default company. This makes the KPI more reliable for people who work across multiple companies and avoids undercounting in the digest report.
Original PR description
**Problem:** Currently, the digest KPI for connected users checks the "company_id" field (as with all other models), but this field corresponds to "Default Company" on res.users, meaning a user can only be considered for one company when computing the digest KPI. This can cause misleading digest KPIs if users work in multiple companies, or mainly in a company that isn't their default company. **Solution:** Instead of always using the "company_id" field, we use the "company_ids" field if present on the model. opw-5404940 Forward-Port-Of: odoo/odoo#259345 Forward-Port-Of: odoo/odoo#247806
This change corrects a bug in the upgrade script so it properly recognizes when a variable is actually being used, even if it is followed by a comma. This prevents the script from making unnecessary template changes during upgrades.
Original PR description
When a variable is used as method parameter and followed by a comma it failed to be identified as being used, so the script then incorrectly moved it as a t-call parameter while it's not necessary.
In the example below, the variable `geoip_country` was not correctly identified as being used in the `t-out` statement:
```
<t t-name="website.test">
<t t-call="website.layout">
<t t-set="geoip_country" t-value="request.geoip.country_code"/>
<t t-set="all_countries" t-value="{cc.code: cc.name for cc in request.env['res.country'].search_fetch([], ['code', 'name'])}"/>
<div>Country: <t t-out="all_countries.get(geoip_country, 'BE')"/></div>
</t>
</t>
```
This commit fix used variable detection when the variable is immediately followed by a comma.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#258838This change prevents an error when downloading a receipt for a POS order in an Indian company. It ensures the receipt is generated using the correct company context, so the required receipt information is included and the download completes successfully.
Original PR description
When a user attempts to download a POS order receipt for an Indian company, a traceback is raised. Steps to reproduce the error: - Install ``l10n_in_pos`` module with demo data - Switch to IN Company…
When a user attempts to download a POS order receipt for an Indian company, a traceback is raised. Steps to reproduce the error: - Install ``l10n_in_pos`` module with demo data - Switch to IN Company - Open a PoS Session > Create an order > Payment > Validate - Navigate to the backend - Go to Orders > Open the created order > Download Receipt Traceback: ``` QWebError: Error while rendering the template: KeyError: 'l10n_in_hsn_code' Template: point_of_sale.pos_orderline_receipt_information ``` https://github.com/odoo/odoo/blob/9fe02a4585ce139c2ea20e9d282bc92f37b7cad7/addons/point_of_sale/controllers/main.py#L24 Here, ``order_receipt_generate_image`` method is called using the current request environment. As a result, the active company becomes the user's current company instead of the POS order’s company. Because of this mismatch, the condition that adds ``l10n_in_hsn_code`` to the POS data fields (based on the company’s fiscal country) is not satisfied at [1]. Consequently, the field is missing from the receipt line data at [2], and the template raises a KeyError when trying to access it. [1]: https://github.com/odoo/odoo/blob/9fe02a4585ce139c2ea20e9d282bc92f37b7cad7/addons/l10n_in_pos/models/pos_order_line.py#L21-L24 [2]: https://github.com/odoo/odoo/blob/9fe02a4585ce139c2ea20e9d282bc92f37b7cad7/addons/point_of_sale/receipt/pos_order_receipt.py#L76 sentry-7417101015 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes how employee birth dates are read from certain Belgian national identity numbers. Some special “bis” numbers use a shifted month value, and the system now normalizes it correctly so valid dates are not rejected.
Original PR description
The NISS month field can be increased by 20 or 40 for "numéros bis". This caused invalid date parsing. Use modulo 20 to normalize the month before constructing the birthday. task-6144297
This fix ensures that calendar leave entries without a specific resource are no longer ignored. Instead, they are applied across all resources as intended, helping planning and availability stay accurate.
Original PR description
Before this commit, any `Resource Calendar Leave` created with no `Resource` related to it was ignored, while it should have been applied to all `Resources`. This commit makes sure that any `Resource Calendar Leave` with no related `Resource` is applied to all `Resources` as intended. task-5798796 Forward-Port-Of: odoo/enterprise#112575
This change fixes a test setup issue in the electronic invoice export module. It prevents a startup error during automated tests when a security group is checked before its module is fully confirmed as installed, making test runs more reliable.
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
Searching for settings on mobile no longer triggers an error. This makes it easier for users to quickly find the right configuration option while using the app on a phone or tablet.
Original PR description
Before this commit, when searching a setting in mobile a error as raised. opw-6140257 Forward-Port-Of: odoo/odoo#260311
This change improves how Odoo checks search filters before they are used. It now catches invalid values, such as text entered where a number is expected, helping prevent errors later in processing and making validation more reliable.
Original PR description
`Domain([('num_field', '=', 'dfd')]).validate(model)` should raise an exception because 'dfd' is not a valid number. Currently, the optimization does not check the data types for all operators, but these are checked during SQL generation. Let's generate the SQL to validate the domain.
task-6132976
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#260102This fix ensures that queries with ordered result IDs still look like they have restrictions when other parts of the system check for them. It preserves existing behavior and prevents related code from misreading these queries as unrestricted.
Original PR description
Some code uses `if query.where_clause` to detect if there are any restrictions on the table. When setting ordered result ids, we simply used a JOIN, so there is no detected where clause. To keep existing code working, we add a dummy 1=1 to the where clause. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260306
This change preserves the visual link styling in frozen and shared spreadsheets while still preventing those links from being clicked on public pages. It matters because dashboards keep their intended layout and appearance without exposing usable internal links.
Original PR description
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that…
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that we'd somehow leak internal views information in the links), cells with links benefit from a specific style that is not hardcoded on the cell but rather computed based on their content. By removing the links from teh cells altogether, the greenish link style is lost on those cells and we actually rely on that style for our dashboards layout. To preserve the intension of https://github.com/odoo/odoo/pull/166843, we introduce a new type of links `neutralized` which allows the cell to be recognized as a link (and benefit from the style) while disabling their behaviour (no click). Task-6063301 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#260250 Forward-Port-Of: odoo/odoo#256357
This update fixes an issue where Adyen payments could fail when capturing or canceling an authorized payment. It also ensures the related transaction record updates correctly, so payment statuses stay accurate after these operations.
Original PR description
Issue 1: --- Capturing/voiding transaction is failing with the error: `The payment provider rejected the request. Original pspReference required for this operation` Steps to reproduce: 1- Setup Adyen…
Issue 1: --- Capturing/voiding transaction is failing with the error: `The payment provider rejected the request. Original pspReference required for this operation` Steps to reproduce: 1- Setup Adyen payment provider. 2- Enable `Capture amount manually`. 3- Create a SO and confirm. 4- Generate a payment link and pay. 5- In SO, capture the full amount. Cause: --- After https://github.com/odoo/odoo/commit/efc2788dfccd13ee6feb309430ff57e49664ff97, in the payment `_void()`/`_capture()`, a child tx is created. However the child tx is missing the `provider_reference` required to send the payment provider. Issue 2: --- The child tx created for capture/void is always remains in draft state. Cause: --- This is reproduced after https://github.com/odoo/odoo/commit/efc2788dfccd13ee6feb309430ff57e49664ff97 which we create a child tx in capture/void. But in `_search_by_reference` which is called by webhook to find the tx, we are returning the source tx. As a result only the state of the source tx is changed. opw-6120846 opw-6120071 Forward-Port-Of: odoo/odoo#259223
18 changes
Resolved issues and error corrections
Fixed an issue in the Forum help page where clicking a snippet category could fail to insert content. This restores a smooth editing experience by allowing the editor to use the only available insertion area when needed.
Original PR description
Steps to reproduce the issue: - Go to Forum, then go to the Help page - Enter Edit mode - Try to drag and drop a snippet => The dropzone in the s_cover at the top of the page are available - Try to click on a snippet group => Nothing happen, because all dropzones are filtered The s_cover element has the [data-snippet] attribute. When clicking on a snippet group, the editor filters out dropzones inside other snippets. Since s_cover is treated as a snippet, its dropzones are excluded, even though they are the only ones available on the page. The solution is to treat dropzones inside snippets as low priority instead of strictly forbidden. If no other valid dropzones exist, we allow these as a fallback to ensure snippet insertion remains possible. task-5938138 Forward-Port-Of: odoo/odoo#258487 Forward-Port-Of: odoo/odoo#256078
This change updates Peru e-invoicing test files so they match the corrected unit price rounding used in PEPPOL. It does not change business behavior for customers, but it keeps automated tests accurate and prevents false test failures during development and delivery.
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
This change removes an unhelpful tooltip that appeared when users hovered over boolean fields in calendar popups. It improves the user experience by preventing confusing HTML content from showing up where no extra information is needed.
Original PR description
Before this commit, the tooltip of a boolean field in calendar popover shows html content when the user hovers the boolean field. This commit removes the tooltip of boolean field in calendar popover since the information inside that tooltip is not really useful for the user. Issue found during the development of task-5994205 Forward-Port-Of: odoo/odoo#259529 Forward-Port-Of: odoo/odoo#259011
This fix ensures that existing checks can still recognize when a data query has restrictions, even when results are returned in a sorted order. It prevents unexpected behavior in parts of the system that rely on that check and helps maintain consistent results.
Original PR description
Some code uses `if query.where_clause` to detect if there are any restrictions on the table. When setting ordered result ids, we simply used a JOIN, so there is no detected where clause. To keep existing code working, we add a dummy 1=1 to the where clause. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update refreshes the automated performance test expectations for website modules when demo data is present. It helps keep test results accurate and prevents false failures during validation, without changing end-user functionality.
Original PR description
Query counts were updated for demo data. runbot-242325 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures the Update Payment button disappears when it should after payments are reconciled on Mexican invoices. It corrects a case where batch payments could make the system think an update was still needed, even though the payment information was already complete.
Original PR description
- Create one invoice with the PUE payment policy. - Create another invoice with the PDD payment policy. - Send both invoices to the CFDI. - Create a batch payment for both and reconcile. - Click on Update Payment on one of the invoices. The Update Payment button does not disappear. In the method _l10n_mx_edi_cfdi_invoice_get_payments_diff, we compare the current UUIDs and the previous UUIDs to determine if the button should be shown. However, when there is a batch payment, the current UUID list includes the UUIDs of all invoices in the batch, including the PUE payment (which should normally be filtered out by the continue). The previous UUID list includes only the UUID of the PDD payment. opw-6055781 Forward-Port-Of: odoo/enterprise#112520
This update removes unnecessary fields from the data sent to the self-order front end. It helps keep the information payload lighter and reduces wasted processing without changing the user experience.
Original PR description
Fix _generate_return_values to remove some fields that are not needed on the frontend Forward-Port-Of: odoo/odoo#260016 Forward-Port-Of: odoo/odoo#259915
The website editor now correctly shows the translation status on file names added through the file tool, even when other background colors would previously hide it. This makes it easier for users to see which content still needs translation while editing a site.
Original PR description
Commit cbb2eb2edfeecbc21a70c1a3cba81ad0a7ac9c75 added a resource to repeat the background color of the translation state inside elements, for the cases where an element has a background color that hides the translation state. This commit uses the resource for file's names (added by typing `/file`) Steps to reproduce: - Open website builder - Type `/file` and add a file - Add a language - Open in translate mode - Bug: the translation state is not show on the file name task-6038029 Forward-Port-Of: odoo/odoo#259955 Forward-Port-Of: odoo/odoo#259902
This fix ensures that events with unlimited ticket availability can be sold correctly from the Point of Sale, even when multiple time slots are enabled. Previously, these tickets could be incorrectly treated as unavailable, causing customers to see an error that all slots were full.
Original PR description
**Steps to reproduce:** - Make an event, put it to announced state - Allow multi slots and create a product - Go to the pos and try to order it - "All slots are booked out for this event" appears **Why the fix:** When we set 0 as a maximum quantity for an event slot, the quantity is unlimited, in the code, the availability is set to a string "unlimited". This was not taken into account in the case of multi slots, as we only checked if the availability was a number greater than 0. As "unlimited" is not a number, we thought we didn't have any slots available and returned the error that said all slots were full. We now add the unlimited tickets to the availability list. opw-6006696 Forward-Port-Of: odoo/odoo#254220
This update adjusts an internal check used to decide when a browser compatibility patch should be considered outdated. It helps keep accessibility-related behavior aligned with the newer lxml 6.1 release, reducing the risk of unnecessary or stale patching.
Original PR description
Whitelisting of ARIA attributes is now part of the milestone for LXML 6.1. This commit updates monkey patch's obsolescence detection accordingly.
The Intervat configuration is now shown for companies using Belgian taxes through a Belgian fiscal position, not only for companies registered in Belgium. This lets users review, change, or disable Intervat redirection when it was previously hidden.
Original PR description
### Issue: When demo data is disabled, creating a Belgian fiscal position installs the Belgian taxes and enables BE accounting Starting from 19.0, Intervat redirection is enabled automatically, but the Intervat settings are not available because the company itself is not Belgian As a result, the Intervat configuration cannot be changed or disabled ### Cause: The Intervat settings were only shown when the company country was Belgium However, companies using Belgian taxes through `account_enabled_tax_country_ids` must also be considered ### Steps to reproduce: - Disable demo data and install `accountant` - Create a Fiscal Position "Belgium" (Country: Belgium, Foreign Tax ID: BE010203040) - Click the alert to install the Belgian taxes - Open Settings Before the fix: The Intervat settings are not available opw-6068480 Forward-Port-Of: odoo/enterprise#112609
When a product belongs to categories from multiple websites, Odoo now chooses a category that is available on the website the customer is currently browsing. This prevents category breadcrumb links from leading to a 404 page and improves the shopping experience across multiple websites.
Original PR description
An issue is observed when two categories share the same name but are assigned to different websites, and a product is linked to both categories. Steps to Reproduce: ==================== 1. Create two…
An issue is observed when two categories share the same name but are assigned to different websites, and a product is linked to both categories. Steps to Reproduce: ==================== 1. Create two Ecommerce categories with the same name, one assigned to Website 1 and the other to Website 2. 2. Create a product and assign both categories to it. 3. On Website 1, navigate to the product page and click the category breadcrumb → works correctly 4. On Website 2, navigate to the same product page and click the category breadcrumb → **404 error** Cause: ====== In `_prepare_product_values`, when no category is passed in the URL, the fallback was: https://github.com/odoo/odoo/blob/a253cff9039fcf729a9922b119acad5ec7c7a0bd/addons/website_sale/controllers/main.py#L802 This blindly picks the **first** category from the product's public categories without checking which website it belongs to. If the first category (by ID order) belongs to Website 1, it gets used even when the user is browsing Website 2. The breadcrumb then generates a slug pointing to Website 1's category. When clicked on Website 2, `can_access_from_current_website()` fails for that category, resulting in a 404. Solution: ========= Filter `public_categ_ids` through `can_access_from_current_website()` before selecting the first one. opw-6070191 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#258336
The call menu in Discuss now includes the Picture-in-Picture option, making it faster to keep a call visible while moving to another conversation or chatter. This also corrects the menu styling so the Fullscreen and Picture-in-Picture actions display with normal visibility.
Original PR description
Before this commit, Call Menu did not have the "Picture-in-Picture" action. This is unfortunate because this is one of the most valuable action to have it available there, as a frequent usage of…
Before this commit, Call Menu did not have the "Picture-in-Picture" action. This is unfortunate because this is one of the most valuable action to have it available there, as a frequent usage of Discuss is to join a call, switch to another conversation or chatter, and then wanting to keep an overlay of the call. Without the "Picture-in-Picture" in Call Menu, this forces user to access the Discuss conversation again and then click on "Picture-in-Picture" there, when clicking on the call menu would be faster. This commit adds the "Picture-in-Picture" action in the call menu to ease using this feature. Also fixes an issue where "Fullscreen" and "Picture-in-Picture" actions have reduced opacity in the Call Menu. This comes from opacity hover effect that should be limited to their inline visual in the Call view but was mistakenly also present in the dropdown. Before / After <img width="440" height="369" alt="Screenshot 2026-04-17 at 14 15 58" src="https://github.com/user-attachments/assets/2accb779-28f5-4930-a101-db5e52b029b7" /> Forward-Port-Of: odoo/odoo#259866
This update fixes an error that could appear when users create accrual entries from the Billed Not Received screen after changing the date. It ensures the date is handled correctly so the action completes normally without interrupting accounting work.
Original PR description
**Steps to reproduce:** - Install the `accountant` and `purchase` modules. - Create and confirm a Purchase Order (with 1 quantity). - Create a vendor bill using `auto-complete` from the PO, set the…
**Steps to reproduce:** - Install the `accountant` and `purchase` modules. - Create and confirm a Purchase Order (with 1 quantity). - Create a vendor bill using `auto-complete` from the PO, set the quantity to 1, and `confirm` it. - Navigate to Accounting > Review > `Billed Not Received`. - Change the `date` from the top left. - Select a record and click `Create Accrual Entries`. **Error:** `TypeError: '<=' not supported between instances of 'datetime.date' and 'str'` **Root cause:** At [1], the `accrual_entry_date` is set in the context as a `string`. Later, at [2], this value is retrieved from the context and used directly in a comparison with `ivl.date`, which is a `datetime.date`. **Fix:** This commit converts `accrual_entry_date` to a `datetime.date` object at [2], allowing users to create accrual entries without errors. [1]: https://github.com/odoo/enterprise/blob/3ab460a935c6caf013202ec6be1c3708178c8d7d/account_reports/static/src/views/accrual_list_controller.js#L61-L76 [2]: https://github.com/odoo/odoo/blob/7e17c788babc2715e85456467db9172bb0b8e42d/addons/account/wizard/accrued_orders.py#L166-L188 opw-6110907 Forward-Port-Of: odoo/odoo#259047
This update preserves the visual formatting of spreadsheet cells that contain Odoo links when a dashboard is frozen and shared. The links are made non-clickable for public viewers, while keeping the same link-like appearance needed for layout consistency.
Original PR description
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that…
Since https://github.com/odoo/odoo/pull/166843, we remove the odoo links entirely from the spreadsheet on `freeze and share`. While it is true that the link is not usable from a public page (and that we'd somehow leak internal views information in the links), cells with links benefit from a specific style that is not hardcoded on the cell but rather computed based on their content. By removing the links from teh cells altogether, the greenish link style is lost on those cells and we actually rely on that style for our dashboards layout. To preserve the intension of https://github.com/odoo/odoo/pull/166843, we introduce a new type of links `neutralized` which allows the cell to be recognized as a link (and benefit from the style) while disabling their behaviour (no click). Task-6063301 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#260250 Forward-Port-Of: odoo/odoo#256357
This change fixes a test that could fail during setup because it checked access groups before confirming the related module was installed. It helps keep automated tests stable and prevents unnecessary errors in the electronic invoicing area.
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
This change fixes a problem where manual capture and void actions could fail in Adyen payments, and ensures the related payment records are updated correctly. As a result, businesses can complete payment operations more reliably without transactions getting stuck or rejected.
Original PR description
Issue 1: --- Capturing/voiding transaction is failing with the error: `The payment provider rejected the request. Original pspReference required for this operation` Steps to reproduce: 1- Setup Adyen…
Issue 1: --- Capturing/voiding transaction is failing with the error: `The payment provider rejected the request. Original pspReference required for this operation` Steps to reproduce: 1- Setup Adyen payment provider. 2- Enable `Capture amount manually`. 3- Create a SO and confirm. 4- Generate a payment link and pay. 5- In SO, capture the full amount. Cause: --- After https://github.com/odoo/odoo/commit/efc2788dfccd13ee6feb309430ff57e49664ff97, in the payment `_void()`/`_capture()`, a child tx is created. However the child tx is missing the `provider_reference` required to send the payment provider. Issue 2: --- The child tx created for capture/void is always remains in draft state. Cause: --- This is reproduced after https://github.com/odoo/odoo/commit/efc2788dfccd13ee6feb309430ff57e49664ff97 which we create a child tx in capture/void. But in `_search_by_reference` which is called by webhook to find the tx, we are returning the source tx. As a result only the state of the source tx is changed. opw-6120846 opw-6120071 Forward-Port-Of: odoo/odoo#259223
This change fixes an issue where invoicing a kit could miss the cost-of-goods-sold entry if one of its components had been removed from the delivery. It also improves the calculation so the cost entry reflects only the components actually delivered, which makes accounting more accurate.
Original PR description
Steps to reproduce: - Create a kit with 3 or more components - Create a sales order with the kit and confirm it - Remove at least one of the kit's components from the delivery and validate it - Create the invoice from the sales order and confirm the invoice - Check the journal entries included in the invoice form Current behavior: - There is no COGS entry Expected behavior: - There should be a COGS entry Context: In versions <19, you will get a COGS entry that amounts to the total cost of the kit despite deleting a component from the delivery. With our current code in versions 19+, we can actually improve upon this by only counting the remaining components' costs for the COGS entry's amount. opw-6082565 Forward-Port-Of: odoo/odoo#258982
1 change
Resolved issues and error corrections
When users create a new vendor bill by auto-completing from a previous bill, the Intrastat details now carry over correctly. This prevents missing trade-reporting information on copied invoice lines and reduces manual correction work.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
9 changes
Resolved issues and error corrections
The web client now correctly handles action buttons even when they do not have a visible label. This ensures the system can tell whether a close or discard button triggered the callback, improving reliability in user flows that depend on that result.
Original PR description
View buttons with no name cause onClosed to be called without any parameters even if special=true or dismiss=true. This commit fixes that which allows to know if a close/discard button caused the action onClosed callback. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change reverts a previous adjustment that caused child contact display names to appear incorrectly. It helps ensure customer and invoice information is shown in the expected format again, reducing confusion in printed documents and business records.
Original PR description
This reverts commit 0ef4c1d06fdf999ad5cdad696069aec8f2f943c5. opw-5900567 Forward-Port-Of: odoo/odoo#260097 Forward-Port-Of: odoo/odoo#260065
This fix corrects how activity filters are combined in Studio-created apps. Previously, "My Activities" could be mixed with "Late Activities" in a way that showed too many records; now the filters work together as expected, improving the accuracy of task and activity views.
Original PR description
Follow-up of 475a9efe0bde7515c9d5bf6ec6c8aefd4c71975e Steps to reproduce ================== - Create an app with studio and use_mail - Create three records, one with an activity in the past, one today and one in the future - Click on the clock status icon in the top right - There should be a section with the new model - Click on 1 Late => every records is displayed The filters "My Activities" is combined with "Late Activities" with and OR. It should use the AND operator. Solution ======== Add a separator after the "My Activities" filter. The same is done in xml for standard models. opw-6069150
This fix stops Discuss from crashing when records are deleted in the background. It also prevents the wrong item from being removed in certain cases, which could leave the interface in an inconsistent state.
Original PR description
Backport of https://github.com/odoo/odoo/pull/251769 Before this commit, Discuss code may crash with the following error: ```js TypeError: Cannot read properties of undefined (reading '_raw') ```…
Backport of https://github.com/odoo/odoo/pull/251769 Before this commit, Discuss code may crash with the following error: ```js TypeError: Cannot read properties of undefined (reading '_raw') ``` This happens because delete operations in JS models could lead to inconsistent state of record lists. Deletion of a record is done internally as follow: ```js const index = recordList.indexOf(record); recordList.splice(index, 1); ``` This is done that way as to reuse custom methods of `RecordList`, especially the `splice()` that is used by many methods that mutate the record list. Internal code of the custom `splice` method does `slice()`, which is used to retrieve some records without mutating the record list. In practice, these `.slice()` were accidentally mutating the list, because they invoke the `Proxy.getter` of the `RecordList`, and when the list is flagged for `computeOnNeed` / `sortOnNeed`, invoking this `Proxy.getter` would mistakenly enable the `computeInNeed` / `sortInNeed` flags and thus mutate the list, e.g. with a sort, which may change the order of items and mess up the `index` computed in `indexOf()` step. This is what might happen with deletion of any item in record list. For example, let's have `menuThreads` that have this value: ```js menuThread = ["thread_1", "thread_2", "thread_3"]; ``` With the removal of `thread_2`, the `.indexOf()` is `1`, but due to `.slice()` triggering the sort, the list was changed to: ```js menuThread = ["thread_2", "thread_1", "thread_3"]; ``` ... And it instead removed `thread_1` but kept `thread_2` in list. This introduce 2 problems: - `thread_1` is mistakenly removed from relation when it shouldn't - `thread_2` is kept, but since this is a local id with no actual record in store, `recordList[index]` would return `undefined` as there's no existing record matching this local id. This commit fixes the issue by improving internal code of record list methods to avoid accidental triggering of lazy re-compute and re-sort. The accidental re-compute and re-sort come from invoking non-implemented array methods on the proxy of record, such as: - `recordProxy.at()` - `recordProxy.slice()` These methods were just used meant to retrieve records from the record list, and they did so by using accessing through `recordProxy`. This approach has the benefit to look good as this is exactly the same as the external API, but it has the unintended side-effect of the re-compute / re-sort of lazy fields. Instead of using these methods, records are retrieved with: - raw access to get local ids in relation - convert local ids to raw records through raw access in `store.recordByLocalId` This approach, while uglier, has the benefit to not accidentally trigger the re-compute / re-sort. Task-4793779 Forward-Port-Of: odoo/odoo#260109
When a sales order for a subcontracted service is increased, the related purchase order now uses the correct quantity. This prevents the system from multiplying the extra quantity twice and creating an unexpectedly large purchase order.
Original PR description
Steps to reproduce the bug: - Create a service product "P1": - In the Purchase tab: - Vendor: Azure Interior - Subcontract Service: True - UoM: dozen - Purchase UoM: unit - Create a sales order with…
Steps to reproduce the bug:
- Create a service product "P1":
- In the Purchase tab:
- Vendor: Azure Interior
- Subcontract Service: True
- UoM: dozen
- Purchase UoM: unit
- Create a sales order with 1 dozen of P1
- Confirm -> a purchase order with 12 units of P1 is generated
- Confirm the purchase order
- Go back to the sales order:
- Update the quantity from 1 to 2 dozen
Problem:
A new purchase order is generated, but with 144 units instead of 12
units. The quantity difference between the old SO quantity and the new
one is computed twice in the purchase order line UoM, in both
`_purchase_increase_ordered_qty` and `_purchase_service_prepare_line_values`:
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L186
Solution:
The `quantity` parameter must be expressed in the SO line UoM, as
described in the documentation of the function `_purchase_service_prepare_line_values`.
https://github.com/odoo/odoo/blob/17.0/addons/sale_purchase/models/sale_order_line.py#L178
opw-6049106
Forward-Port-Of: odoo/odoo#257637
Forward-Port-Of: odoo/odoo#255478This change fixes an access problem that prevented some users from printing product and product variant labels, even when they only needed to view the products. It restores the expected behavior so staff with read access can use label printing without needing extra permissions.
Original PR description
Users who do not have the "write" access on `product.template` and `product.product` cannot print product labels and product variant labels Steps to reproduce: 1. Install Sales 2. Log in as Marc Demo…
Users who do not have the "write" access on `product.template` and `product.product` cannot print product labels and product variant labels Steps to reproduce: 1. Install Sales 2. Log in as Marc Demo 3. In Sales > Products > Products, open a product and click Print Labels from the cogwheel menu 4. An access error is raised Same issue happens for Product Variants Issue: https://github.com/odoo/odoo/commit/95ace0a694eaf83329b50e6b89f774f0c59fec5e removed Products-related rights from the `base.group_user`. This made a difference in terms of access rights, as the `IrActionServe.run` method checks for the "write" access by calling `_can_execute_action_on_records`: https://github.com/odoo/odoo/blob/d15685304f479541879fabd55ea1cae4252a2a90/odoo/addons/base/models/ir_actions.py#L1230-L1239 Solution: Add `group_user` to the `group_ids` of the relevant actions to prevent the check on the "write" access from being performed This is a backport of https://github.com/odoo/odoo/commit/6c2c353f30db05579f5e8b7a6752ec2d1ae365b2 opw-6111333
This change corrects a test setup issue in the UBL export module so it no longer fails while checking required security groups. It helps keep automated tests stable and prevents false failures during installation checks.
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
Auto-completing a vendor bill now correctly keeps its Intrastat information when the source bill already had it. This prevents missing trade reporting data and helps ensure the generated bill is complete and compliant.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
This fix prevents an error when exporting the General Ledger in a Peru company if draft invoices or other draft entries are included. Users can now complete the export without the report breaking, improving reliability for accounting work.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
1 change
Resolved issues and error corrections
This change prevents an error when generating a W-2 CSV report if no end date is entered. The system now uses the current year for the file name in that case, so users can complete the export without interruption.
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#1134085 changes
Resolved issues and error corrections
This fix restores document uploads for portal users on mobile devices when sharing folders with edit access. It keeps the upload menu open long enough for the file selection to complete, so uploads start reliably after choosing a file.
Original PR description
Steps to reproduce: 1. Install `documents` 2. Create a portal user and share a document folder with edit access 3. Log in as the portal user on a mobile device 4. Try to upload a document inside the…
Steps to reproduce:
1. Install `documents`
2. Create a portal user and share a document folder with edit access
3. Log in as the portal user on a mobile device
4. Try to upload a document inside the shared folder
Issue:
- After selecting a file from the file picker, the document is not uploaded.
Cause:
- On mobile in the portal flow, Upload is triggered from a nested dropdown (inside New) inside the adaptive control-panel dropdown (bottom sheet). By default, DropdownItem uses closingMode="all", so tapping Upload closes parent dropdowns immediately. That unmounts the hidden <input type="file"> before the OS file picker returns. When the user comes back, the input no longer exists, so change never fires and upload does not start.
- Admin/internal users do not hit the same nested adaptive-dropdown path in this view
Solution:
- Set closingMode="'none'" on the Upload DropdownItem so the menu stays mounted while the native picker is open. After a file is selected and onFileInputChange starts upload, close the bottom sheet programmatically with: `window.dispatchEvent(new Event("popstate"))`
opw-5937105When a packed product is scanned with its lot and due date information, the system now correctly keeps the expiration date instead of replacing it with today’s date. This ensures lots created during barcode operations retain the right expiry information, which helps avoid inventory and delivery errors.
Original PR description
Issue
-----
Scanning a GS1 barcode containing:
- packaging
- lot
- due date
disregards the due date when creating the new lot.
Steps to reproduce
-----
- Enable GS1 nomenclature & packagings
- Create a product
- barcode 23456789012344
- packaging with barcode 01234567890128
- some on hand quantity
- Create a delivery for a full packaging of the product
- Open the delivery in barcode
- Scan 02 01234567890128 15 270101 10 LOT1
- Validate
- Open the lot
> Expiration date is set to today
Cause
-----
The code expects the product be scanned, there is no logic to retrieve it from the packaging when missing.
-----
Ticket:
opw-6073489
Forward-Port-Of: odoo/enterprise#114123
Forward-Port-Of: odoo/enterprise#112490This update fixes two issues affecting project creation from sales orders. It now correctly uses the delivery address for the project customer and avoids a conflict that could block creating FSM projects from a template. This makes the sales-to-project flow more reliable for users.
Original PR description
FIX 1: industry_fsm_sale: set delivery address on project customer] ----------------------- **Steps to reproduce:** - Create a product: - Product Type: Service - Service Tracking: Create on Order…
FIX 1: industry_fsm_sale: set delivery address on project customer] ----------------------- **Steps to reproduce:** - Create a product: - Product Type: Service - Service Tracking: Create on Order (project) - Project Template: FSM type project template - Confirm a sale order with this product - Check the generated project customer **Issue:** The customer's delivery address is not set on the generated project. **Fix:** Set the delivery address as the project customer when creating the project. [FIX] industry_fsm_sale: remove default sale line in fsm projects ------------ **Steps to reproduce:** - Install industry_fsm_sale - Create a project template of fsm type - Create a sale order (service-type product) - Confirm the sale order - Create a project and select the fsm-type project template - Create the project **Issue:** - SQL constraint is triggered, preventing project creation. **Fix:** - If the project template is of fsm type, remove the default sale line from the context. task-5074893
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)
8 changes
Resolved issues and error corrections
This update fixes an issue in Point of Sale where orders paid with an eWallet could be incorrectly turned into credit notes instead of invoices. The problem was caused by tiny rounding differences, and the fix ensures the system makes the correct document type and keeps quantities accurate.
Original PR description
**Steps to reproduce:** - Make a $10 product, the tax must be tax included - Set up an ewallet - Open the PoS, order the created product and add the ewallet - Ask for an invoice and complete the payment - The generated invoice is a Credit Note **Why the fix:** When chosing the invoice's move_type (invoice or credit note), we check if the total amount is greater or equal to 0, and if it is, we make an invoice, else we make a credit note. This did not work correctly as with the tax included product there was a tiny bit of difference between the product's price and what the ewallet covered. This means that the total was just a tiny bit under zero, and was treated as a refund, so a credit note was then created. The same problem was observed when preparing the invoice lines, the order was treated as a refund, so the lines' qty were inverted. We now use float_compare to avoid such rounding issues. opw-5490407
This fix prevents an error when exporting the General Ledger in the Peru localization, especially when draft invoices or entries are included. Users can now complete the export successfully without the report stopping due to missing entry names.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117
When users create a vendor bill by auto-completing it from a previous bill, the Intrastat transaction information is now kept on the copied lines. This prevents missing reporting data and helps ensure cross-border trade declarations remain complete and accurate.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
This update ensures bpost correctly recognizes European Union destinations regardless of the user’s language. As a result, shipments within the EU will no longer be incorrectly treated as non-EU and forced to include customs details such as HS codes.
Original PR description
Since #101476, the EU country group was retrieved by searching on the name field of res.country.group. Because this field has `translate=True`, Odoo resolves it against the current user's language at query time. For non-English users, the search for "European Union" would return no results, causing every destination country to be treated as outside the EU, meaning HS codes were incorrectly required for all bpost shipments, including intra-EU ones.
Replaced occurrences with env.ref("base.europe"), which resolves the record via its external XML ID and is fully language-independent.
opw-6139450This fix makes the kiosk’s online payment page display in the user’s selected language instead of always showing the QR code payment message in English. It improves the customer experience for multilingual setups and helps make the payment flow feel consistent and localized.
Original PR description
Currently if you use an online payment with the kiosk, the payment page with the QR code is not translated. Steps to reproduce: ------------------- * Create an online payment method with demo * Install any language, you don't need to switch * Open kiosk configurations * Set the online pm in the available payment methods * Set the language istalled as the default language * Make an order, go to payment page > "Scan the QR code to pay" is written in english no matter the language opw-6074194
Contact list views now show related contact types in the user’s language instead of always displaying them in English. This makes contact names consistent across views and improves the experience for multilingual users.
Original PR description
Problem: When the contact type is set for a related (child) contact, the contact type is shown in English next to the contact name in the contact list view. It should be translated to the user language. It is correctly translated in the Kanban view. Steps to reproduce: 1. Install the Contacts app. 2. Create a contact or go to an existing contact 3. Add a related (child) contact and set its contact type to any type (i.e. Invoice Address) 4. Change the user language to any language other than English 5. Go back to the contact list view and check the name of the related (child) contact. See how the contact type appearing in the name is in English instead of being translated, while it is correctly translated in the Kanban view. Cause: The list view uses the 'complete_name' field which is not translated, while the Kanban view uses the 'display_name' field which is translated. Solution: Use the 'display_name' field instead of 'complete_name' in the list view. opw-5947987
When a UBL XML invoice is imported into a vendor bill, the chatter now shows the proper import format message instead of an unhelpful "None". This makes the import history clearer for users and ensures the invoice format is always displayed when available.
Original PR description
[FIX] account_edi_ubl_cii: Print right message in chatter at import When a UBL XML invoice is imported in vendor bills and no logs are collected, a message 'None' is printed in the chatter and the message 'Format used to import the invoice: ...' is not printed This commit fixes both issues no-task 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 prevents a test from failing during setup when a related security group module has not been checked for installation yet. It makes the e-invoicing test suite more reliable and avoids an exception during automated runs.
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
5 changes
Resolved issues and error corrections
This update adds an Odoo partner identifier to SendCloud requests so shipments continue to work smoothly with SendCloud’s older API during their transition period. It helps SendCloud recognize traffic coming from Odoo and reduces the risk of service disruption for existing customers.
Original PR description
Sendcloud pass their api v2 to maintenance and only provide new api V3 key to the new customers. In order to make a smooth transition for the user we add the partner key, so they know that the customer are coming from odoo and they use the v2 api. Future work will be done to upgrade our module and support the v3. API key.
The currency rate service now allows the wait time for the mindicador.cl provider to be configured, instead of using a fixed 30-second limit. This helps prevent daily exchange rate updates from being missed when the provider is slow, reducing gaps in currency rate records.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027
This fix ensures that when a product price already includes tax, the invoice line price is recalculated correctly after applying a fiscal position in branch companies. It prevents customers from being charged based on the full tax-included amount when the tax setup should reduce the base price.
Original PR description
When operating in a multi-company branch environment, the unit price of a product with price-included taxes is not correctly recalculated when applying a fiscal position. Steps to reproduce: - Create a tax that is included in the price (e.g., 10% incl). - Assign this tax to a product (e.g., Product A). - Create a fiscal position that maps this 10% tax to a different tax. - Create a branch (child company) of your main company. - Create an invoice in the new branch using the fiscal position and add an invoice line for Product A. Issue: The unit price of the product on the invoice line remains the full tax-included amount rather than being reduced to exclude the original 10% tax. opw-5931302
This change ensures website menus correctly connect to newly created pages, even when the menu URL contains spaces or does not start with a slash. It also adds a warning in the menu editor to help users avoid confusing URLs that may be rewritten when a page is created.
Original PR description
When a menu item URL contains a space and has no leading slash (e.g., "some url"), creating a page from its 404 screen does not link the menu to the newly created page. The menu keeps pointing to a…
When a menu item URL contains a space and has no leading slash (e.g., "some url"), creating a page from its 404 screen does not link the menu to the newly created page. The menu keeps pointing to a 404. **Steps to reproduce**: 1. Create a menu item with a URL containing spaces and no leading slash (e.g., "some url"). 2. Click the menu item -> a 404 page is displayed (expected). 3. Click "Create Page" -> the page is created and saved. 4. Click the menu item again -> it still returns a 404 (unexpected). **Issue**: During page creation, the path is slugified (e.g., "some url" -> "/some-url"). The controller then tries to link the menu to the new page by setting `page_id`. However, `pagenew()` only searches for menu URLs with a leading slash, so a menu saved as "some url" is not found when searching for "/some url". As a result, `page_id` is never set, and `_clean_url()` keeps resolving the menu to "/some url" instead of the page's actual URL "/some-url". Menus without spaces (e.g., "mypage") have the same issue where `page_id` is not set, but since `_clean_url()` prepends "/" and renders "/mypage", which matches the new page URL, the menu still resolves correctly. **Fix**: Match both URL formats (with and without leading slash) when linking a menu to a newly created page. Additionally, a warning is now shown in the menu editor when a URL contains spaces, since spaces are slugified during page creation, which could cause confusion. (Note: this is only a warning - URLs with spaces are still allowed.) task-[5095646](https://www.odoo.com/odoo/project/974/tasks/5095646) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents a manufacturing order from being updated with a Bill of Materials that no longer matches the selected product. It avoids a crash when users try to unbuild such an order, helping keep production and rework workflows reliable.
Original PR description
Currently, an error occurs if a user changes the product in a BoM, updates the manufacturing order (MO) based on that BoM, and then attempts to unbuild the order. ## Steps to replicate: - Install…
Currently, an error occurs if a user changes the product in a BoM, updates the manufacturing order (MO) based on that BoM, and then attempts to unbuild the order.
## Steps to replicate:
- Install Manufacturing without demo data
- Settings > Enable Variants
- Create the following products:
- Car with (Red and Blue Color attributes)
- Red Paint
- Create a BoM for Car and product variant set to Red Car and have Red paint as the component.
- Create and Confirm manufacturing order for Red Car
- Click on Bill of Material > Set Paint required to 2 > Save
- Set product variant in BoM to Blue and save again.
- Go back to MO > Update BoM > Produce All
- Unbuild qty 1 > Confirm
## Observed Behavior:
ZeroDivisionError: float division by zero
## Root cause:
This issue occurs because the Update BoM button remains visible on the Manufacturing Order (MO) even after the product has been changed.
The problem starts when a user initially updates the required paint quantity from 1 to 2. At that point, the function [1] marks the BoM as outdated for all linked MOs, which makes the Update BoM button appear. However, if the user later changes the product template or variant, the BoM is still considered outdated. This incorrectly allows the user to update the MO using a BoM that no longer matches the selected product.
**Why this causes a traceback when unbuilding?**
When the user clicks Update BoM, it triggers the `action_update_bom function` [2], which calls `_link_bom`. This process recomputes several fields to align the MO with the updated BoM. One of the methods triggered during this recomputation is `_compute_move_finished_ids` [3]. Since the production is already confirmed, the logic skips adding the production to `production_with_move_finished_ids_to_unlink_ids`, meaning no new finished moves are created for that updated product.
As a result, although the MO is updated, its finished product (`move_finished_ids.product_id`) still refers to the original product (for example, Red Car), instead of the newly selected one.
Later, when the user attempts to unbuild the product, the `action_unbuild` function [4] is executed, which calls `_generate_consume_moves` [5] During this step, the system tries to compute a factor that depends on `unbuild.mo_id.quantity_produced`.
However, because the finished moves still reference the old product and do not match the MO’s current product, the computed total becomes zero at [6] This leads to a division by zero error at [5], which ultimately causes the traceback.
[1]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_bom.py#L432-L447 [2]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L1044-L1048 [3]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L771-L800
[4]:
https://github.com/odoo/odoo/blob/97b60952d59a57aba12b048cb4da4f41d85d2ea2/addons/mrp/models/mrp_unbuild.py#L153-L164
[5]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_unbuild.py#L225-L232 [6]:
https://github.com/odoo/odoo/blob/444de5354dcd70e9160a985486317a8912d53a84/addons/mrp/models/mrp_production.py#L641-L647
## Solution:
This change prevents users from updating a Bill of Materials (BoM) after the main product or its template has been modified, by ensuring the BoM is not marked as outdated.
This approach make sense because, once a manufacturing order (MO) is confirmed, all raw materials are physically reserved before production begins. While it makes sense to update BoM components in response to an Engineering Change Order (ECO) or last-minute specification changes, it does not make sense to allow changes to the final product itself on existing confirmed MOs. Doing so could lead to operational errors, since materials have already been procured and reserved for a specific product.
This fix ensures that if the product variant or product template is updated in the BoM, users cannot update the MO based on that BoM. This also prevents potential divide-by-zero errors when attempting to unbuild the product in the MO.
Reference commit which also suggests this behavior for the `Update BoM` button: [commit](https://github.com/odoo/odoo/commit/d7392829c769ef50456a7bc93d4482072b329463#:~:text=An%20exception%20however%3A%20if%20the%20MO%20is%20confirmed%20and%20the%20BoM%27s%20product%20was%0Achanged%2C%20the%20MO%20shouldn%27t%20have%20the%20%22Update%20BoM%22%20button%20displayed.%0AOtherwise%2C%20it%20would%20change%20the%20finished%20product%20of%20a%20confirmed%20MO.)
opw-6044754