Friday, July 10, 2026
27 changes · 19.0
Resolved issues and error corrections
This fixes an issue where down payment lines invoiced from the point of sale could lose their description when linked sale order details were not yet available. The invoice now keeps the correct line name, helping customers and staff see clearer invoice details.
Original PR description
When a POS line comes from a sale order, its invoice line name is overridden with the source sale order line's name. When a down payment is invoiced directly from the POS, the invoice is generated before the down payment POS line is linked to its sale order line, so sale_order_line_id is still empty and the override resolved to an empty recordset, setting the invoice line name to False. Only override the name when a sale order line is actually set, so the down payment line keeps its own name. opw-6305649 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Thai Commercial Invoice print option is now limited to sales invoices for companies whose fiscal country is Thailand. This prevents confusing duplicate-looking invoice print choices when Thai localization is installed alongside other country localizations.
Original PR description
The "Commercial Invoice" report action had no domain, so it appeared as a print option for account.move records of any company, not just Thai ones. This caused duplicate-looking invoice print options when another localization was installed alongside l10n_th. Restrict the report's visibility to invoices whose company's fiscal country is Thailand and journal type is Sales. task-6372205
This fix adjusts an API documentation test so it allows enough time when many modules are installed. It helps prevent false test failures in larger setups, improving confidence in automated quality checks without changing user-facing behavior.
Original PR description
The test_cache test failed a couple times on a timeout error, this is because the more modules are installed, the longer it takes to index them all and generate the json document. [runbot-240550](https://runbot.odoo.com/odoo/error/240550)
Self-order kiosk purchases now retain the customer's phone number on the order after terminal payment. This prevents missing contact details in the backend and keeps phone handling consistent with email handling.
Original PR description
When ordering from a self-order kiosk (e.g. with a Stripe payment terminal), the customer's phone number was saved on the created partner but no longer on the order itself (pos.order.mobile stayed…
When ordering from a self-order kiosk (e.g. with a Stripe payment terminal), the customer's phone number was saved on the created partner but no longer on the order itself (pos.order.mobile stayed empty), while the email was correctly registered. Self-order (QR code / mobile) was not affected. Steps to reproduce: ------------------- * Set a POS in kiosk mode with a payment terminal * Place an order and fill in the contact information (email & phone) * Pay through the terminal * Open the order in the backend > Observe that the email is registered but the phone (mobile) is not Why the fix: ------------ The kiosk pays through a second server round-trip (/kiosk/payment), which runs _check_pos_order again on the already created order. There, 'email' falls back to the partner's email but 'mobile' was taken only from the payload. By payment time the phone is no longer in the frontend payload (it is stripped from every self-order response), so the second sync overwrote the mobile saved on the draft with an empty value. The email survived only thanks to its partner fallback. Mirror the email behaviour and fall back to the partner's phone so the mobile survives the payment re-sync, consistently with the mobile field being computed from the partner. opw-6331335 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Sales quotation PDFs no longer show the "Connect your software" message for customers with portal access. This keeps printed quotes consistent for all customers and avoids showing a redundant prompt that is already available in the customer portal.
Original PR description
Steps to reproduce: 1. Install Contacts and Sales 2. Open any of the contacts, click on the gear icon at the top and click on "Grant portal access" 3. Grant access to all contacts 4. Create a Sale Quotation for that contact and print it Issue: The sentence 'Connect your software... ' appears in the pdf when sending the quote to a contact who was portal access, while it does not appear if the contact does not have portal access Expected behavior: Should not appear regardless of whether the customer has a portal account or not since they have it appear as a smart button in their portal. opw-6308357 Forward-Port-Of: odoo/odoo#272893
This fixes a visual glitch in the website editor where resize or padding handles could show an unwanted white line when Chrome was zoomed in or out. The handles now keep a consistent appearance on hover, making page editing feel more polished and reliable.
Original PR description
Steps to reproduce: - Open Chrome. - Set the browser zoom below or above 100%. - Edit a website page. - Hover a resize or padding handle in the overlay. => A white line appears in the middle of the handle. Before this commit, overlay handles changed their inner outline color on hover. With Chrome zoom levels different from 100%, this could leave a white line visible in the middle of the handle. After this commit, overlay handles change their background color on hover and use a consistent inner outline width, so no white line is visible. task-6048647 Forward-Port-Of: odoo/odoo#273722
Payments created from vendor bills opened through a project will no longer incorrectly inherit that project's analytic distribution. This keeps payment journal entries clean and prevents project cost reporting from being distorted by unrelated payment lines.
Original PR description
Steps to reproduce ------------------- - Install sale_project, accountant and project_timesheet_forecast_sale modules; - Activate analytic accounting in the settings; - Add an outstanding account to…
Steps to reproduce ------------------- - Install sale_project, accountant and project_timesheet_forecast_sale modules; - Activate analytic accounting in the settings; - Add an outstanding account to the bank journal’s manual outgoing payment method; - Create a new billable project; - Open the top menu, add vendor bills and open it; - Create a new bill from there, it should use the project’s analytic distribution; - Confirm it and create a payment; - Open the payment’s journal entry, it is using the analytic distribution too; Why is it happening -------------------- When opening a vendor bill from the project, the project_id is added to the account.move's context to use the correct analytic distribution when we create a bill. If we create a payment after accessing the bill from this route, the context is transfered to account.payment.register, and then to the payment's entry lines in the `_create_payments` method. Due to the `_compute_analytic_distribution` method, the project's distribution is used on the payment's entry. We propose to filter out payment lines in this compute method. opw-6329475 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275076
This update adjusts the Indian point-of-sale receipt layout so it remains compatible with related enterprise customizations. It helps avoid display or integration issues when multiple Odoo modules modify the same receipt template.
Original PR description
This commit changes an xpath of a template to make it compatible with other xpaths in other modules. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents an outdated workaround from being applied when newer supported software already includes the fix. It also updates a dependency requirement so Odoo remains compatible with upcoming Ubuntu and Python versions.
Original PR description
In python-stdnum 2.0+, the upstream issue regarding the zeep Transport class timeout handling has been resolved arthurdejong/python-stdnum@6cbb9bc09c25fbda7a032521bc57b44e0ce18ec4), and the method signature for `get_soap_client` was updated to include the `verify` parameter. Applying our legacy monkey patch on python-stdnum >= 2.0 causes signature mismatch issues and is no longer necessary. This commit: - Restricts the `get_soap_client` monkey patch to run only for `python-stdnum < 2.0`. - Updates `requirements.txt` to use python-stdnum 2.2 for Python 3.14+ to ensure compatibility with Ubuntu Resolute. Forward-Port-Of: odoo/odoo#275360 Forward-Port-Of: odoo/odoo#275046
Grouped date and time views now show hours using a 24-hour clock, so afternoon records are no longer mislabeled as early-morning times. This makes reports and list groupings easier to read and prevents confusion when reviewing time-based data.
Original PR description
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents…
Description of the issue/feature this PR addresses:
When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`.
In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views.
Current behavior before PR:
A datetime value in the afternoon is grouped under a 12-hour label without AM/PM.
For example, records around `13:50` are displayed under:
01:00 20 Mar
Similarly, a datetime value around `16:20` may be grouped under:
04:00 26 Mar
This is ambiguous because the group header does not indicate whether the hour is AM or PM.
Example screenshot showing records around 13:xx grouped under `01:00`:
<img width="310" height="240" alt="image" src="https://github.com/user-attachments/assets/8768f2e8-9aaa-436b-af9f-40055a6032e9" />
Desired behavior after PR is merged:
Hour-based datetime group labels should be unambiguous.
The hour grouping format now uses `HH:00 dd MMM`, so grouped datetime labels render using a 24-hour clock.
For example:
13:00 20 Mar
16:00 26 Mar
This fixes the datetime hour grouping label shown in grouped list views and other `read_group` consumers.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#275219
Forward-Port-Of: odoo/odoo#274724The website SEO optimization menu no longer crashes when the same image appears in multiple product page sections. This improves reliability for editors managing product pages and SEO settings, especially in debug mode.
Original PR description
## Problem: when snippets with identical images are added in the e-commerce website product page, the "Optimize SEO" option in debug mode causes an error to occur with a traceback. The traceback…
## Problem:
when snippets with identical images are added in the e-commerce website product page, the "Optimize SEO" option in debug mode causes an error to occur with a traceback. The traceback calls out a duplicate key in the `t-foreach` of a loop over `state.altAttributes`. the `t-key` for this loop is `img.id` which is generated by the `/website/get_alt_images` controller endpoint.
## Steps to reproduce:
1. Go to a product page and click on "go to website" smart nav btn.
2. Add a snippet with an image in the `description_ecommerce` field
3. Add a snippet with the same image in the `website_description` field.
4. In debug mode, open `site > Optimize SEO`
5. An error `Got duplicate key in t-foreach` is thrown.
## Solution:
The solution was simple to add a qualifier in the compound key generated by the controller action for the `id` field. The chosen qualifier in this case was `model['field']`. `field` is the position in the template where the image came from.
So now the keys for the two identical images go
FROM
> `${model}-${id}-${index}`
>
> 1st image of `website_description`:
> `product.template-6-0`
>
> 1st image of `description_ecommerce`:
> `product.template-6-0`
TO
> `${model}-${id}-${field}-${index}`
>
> 1st image of `website_description`:
> `product.template-6-website_description-0`
>
> 1st image of `description_ecommerce`:
> `product.template-6-description_ecommerce-0`
task-6325786
Forward-Port-Of: odoo/odoo#272846The Discuss GIF picker now shows the Klipy attribution required when the Klipy integration is enabled, including a KLIPY search label and a powered-by footer link. This helps deployments using Klipy stay compliant with provider terms while keeping the branding hidden when the feature is disabled. The change also records a corporate CLA signature for Royal Import & Export Ltd.
Original PR description
Description of the issue/feature this PR addresses: Odoo 19 migrated the Discuss GIF picker from Tenor to the Klipy API (c29d45e3, #272493), but the picker UI does not display the attribution…
Description of the issue/feature this PR addresses: Odoo 19 migrated the Discuss GIF picker from Tenor to the Klipy API (c29d45e3, #272493), but the picker UI does not display the attribution required by [Klipy's guidelines](https://docs.klipy.com/attribution). Deployments using a Klipy API key therefore risk non-compliance with Klipy's terms of use. This PR also adds the corporate CLA signature for Royal Import & Export Ltd (doc/cla/corporate/royalimport.md). Current behavior before PR: When the GIF picker is enabled, the search bar shows a generic "Search for a GIF" placeholder and no Klipy branding is visible while browsing GIFs. Desired behavior after PR is merged: When the GIF picker feature is active (discuss.klipy_api_key configured), the picker shows: "Search KLIPY" in the search bar (required by Klipy) A "Powered by KLIPY" footer linking to https://klipy.com/ Attribution is hidden when the feature is disabled. Existing GIF picker tests are updated and a test covers the attribution footer. I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr)
Website editors can now replace a product category image more than once without the media dialog failing to open. This keeps category list editing smooth and avoids requiring workarounds when updating storefront visuals.
Original PR description
Steps to reproduce: - Open the website builder and add the category list snippet - Select a category item and click Replace to change its image - Pick an image from the media dialog and save - Click…
Steps to reproduce:
- Open the website builder and add the category list snippet
- Select a category item and click Replace to change its image
- Pick an image from the media dialog and save
- Click Replace again on the same category item
=> The media dialog no longer opens the second time (nothing happens).
`SetCategoryImageAction.apply` locates the category `<img>` via `el.querySelector('[name=category_image]')` and stores it in `categoryImage`. On save, `categoryImage.replaceWith(selectedImageEl)` swapped the DOM node for the element built by the media dialog.
That new element (built in `ImageSelector.createElements`) only carries `src`, `alt` and `data-attachment-id`; it does not have the `name=category_image` attribute. As a result, the next call to `apply` can no longer find the image via `querySelector`, and returns early before the dialog is opened again.
Fix by updating the existing image's `src` in place instead of replacing the DOM node, so the original element (and its `name` attribute) is preserved across successive replacements.The website shop accordion now shows only one arrow indicator and keeps its color consistent whether sections are open or collapsed. This removes a small visual glitch in the online store interface, improving polish and reducing customer confusion.
Original PR description
In commit[1] we restyled the accordion snippets, removing the background-image to use oi-icons instead. However due to selector specificty, the rule was taking priority. This :not is actually wrong since we want the color to apply as well when the accordion is collapsed (else you have 2 different colors between the collapsed uncollapsed state) task-6361379 [1]: f26a1535b96c728e4360d94c0c06de138a6b1b3f --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274016
Some labels in the website editor were not appearing correctly for color picker and product image carousel options. This update ensures those option titles display properly, making the editor clearer for users configuring website themes and product pages.
Original PR description
Steps to reproduce: - Open the website editor. - Go to the Theme tab. - Inspect the Primary or Secondary color picker title. => The title prop is undefined. - Go to a product page with several product images. - Edit the carousel thumbnail position option. => The Left and Bottom button titles are undefined. Before this commit, some builder option titles were passed as OWL expressions instead of translated string props. After this commit, these titles use translated string props and are properly available to the builder components. task-6034856 Forward-Port-Of: odoo/odoo#275235
This fix prevents Odoo from repeatedly running a French e-invoicing update process when no stored setting has actually changed. The update now runs only when the relevant start date is set, reducing unnecessary background work and improving reliability.
Original PR description
In previous fix https://github.com/odoo/odoo/commit/29b24a17a40d0f45a0e459cda68ca53b7d40075e we called _force_update_l10n_fr_f10_moves when the value of _compute_l10n_fr_pdp_flow_10_start_date changed as if it was stored, whitch it's not, calling the method each time the compute was triggered. Now _force_update_l10n_fr_f10_moves is run when l10n_fr_pdp_annuaire_start_date is set. Forward-Port-Of: odoo/odoo#275019
Point of Sale receipts will no longer include the extra terminal receipt text from Worldline payments. This keeps customer receipts shorter, clearer, and avoids duplicate or unnecessary payment information.
Original PR description
This PR removes the terminal receipt from Worldline we are currently inserting in the Point Of Sale receipt We don't adapt the driver code to get the receipt as we cannot change C method prototypes task-6373975
Czech VAT control statements now place invoices from partners with non-domestic VAT numbers in section A5 instead of A4. This helps keep tax reports compliant by ensuring A4 is reserved for domestic VAT transactions only.
Original PR description
With l10n_cz company: - Create an invoice for a partner with a foreign vat (EU) with an amount greater than 10000 CZ and a 21% tax. In the vat control statement of the tax report, the move is classified under A4. But the section A4 should only contain move with domestic vat opw-6268506
Canadian check printing now hides check numbers on the attached stubs when pre-numbered checks are used. This keeps the printed check and its stubs consistent and avoids duplicate or confusing numbering on payment documents.
Original PR description
The check itself respected the check_manual_sequencing field, but the stubs did not. Hide the numbers on stubs as well, exactly like on US checks. task-6343701 Forward-Port-Of: odoo/enterprise#122565
The Colombian DIAN invoicing module now correctly hides the Reset to Draft option for credit notes that have already been accepted by DIAN. This helps prevent users from accidentally changing official documents after they have been validated by the tax authority.
Original PR description
Issue: The reset button would still appear for credit notes that were already accepted by the DIAN. Steps to reproduce: Create a credit note, confirm it and send it to DIAN. You will be able to select Reset to Draft even though it shouldn't be possible to convert to draft after accepted by DIAN. Cause: The function to compute if the reset button would appear or not was only taking into account Invoices. Solution: Added credit notes, to the function that verifies if the reset button should appear. opw-6219265
The AI website builder now shows the correct preview image for the AI live chat snippet when the related live chat app is not installed. This helps users understand what the snippet will look like before adding or enabling it.
Original PR description
Commit [1] removed the snippet preview since it mismatched the actual result, but it was overlooked that there's another use of this preview. This commit adds an updated image back. [1]: df05441e469157890253b5550b5f8735723b28fb task-6379796
This change ensures subscription commission tests correctly clear currency rate data across companies when demo data is present. It prevents false test failures and helps keep commission calculations reliably validated.
Original PR description
Steps to reproduce: 1- Initialize a new database with demo data 2- Run the test `test_sub_commission_no_currency_rate` Issue: `AssertionError: 0 != 10 : Regular invoice, 10 percent of 100` Why this happens: The test used to delete all rows in the res_currency_rate table for the current company only. When we load the database with demo data, the query in `_get_subscription_currency_rates` would find entries for the other companies and wouldn't resort to the default. Later when joining, it would find no rates for the current company and the test fails. runbot-243440
This fix ensures status messages in French reporting are displayed properly when documents are accepted or rejected. It prevents error details from appearing incorrectly, helping users understand report outcomes without confusion.
Original PR description
A mismatch between error titles and status logs was introduced in 18.0. Markup wasn't added to the status logs, leading to a type mismatch (Markup + str) when displaying errors for 'accepted' or 'rejected' statuses. As a result, the logs were not interpreted as HTML. This commit ensures Markup is applied to each element to guarantee coherence and proper rendering. backport of 5113752 task-6053842 Forward-Port-Of: odoo/enterprise#123250
This fix ensures database API keys are accessed correctly during database management and synchronization workflows. It helps prevent access issues in user management and sync operations, improving reliability for teams managing databases.
The Argentine VAT Book export now handles foreign partners marked as overseas providers without blocking the ZIP download. This avoids manual workarounds and lets businesses correctly generate VAT reports for transactions involving foreign suppliers or partners.
Original PR description
Steps to reproduce: - Create a partner with: - State: Ireland - Identification Number: Foreign ID 55000004153 - ARCA Responsibility Type: Proveedor del Exterior - Create an invoice for the partner - Accounting > Reporting > Tax report - Select Report: VAT Book (AR), Tax Type: Sales - Click on gear icon > VAT Book (ZIP) Issue: Action will be blocked with error "No VAT configured for partner [58] <partner>" Analysis: Partners with ARCA responsibility type 'Proveedor del Exterior' (code 8) and a ForeignID identification type, causes a UserError when exporting the VAT Book (ZIP). Code 8 (foreign provider) is the purchase-side counterpart of code 9 (foreign customer), which already fell back to the country-level VAT. Extend the existing fallback branch to cover both codes. opw-6316008 Forward-Port-Of: odoo/enterprise#123506
This fixes an issue where the Sign app could fail when loading signing fields in debug mode. The change makes the page ignore hidden template comments so users and testers can continue working with documents without interruption.
Original PR description
Use lastElementChild when retrieving the sign item from the target element. In debug mode, inherited templates may introduce HTML comments into the DOM. Since lastChild return a comment node, accessing classList on the returned node raises an error. Using lastElementChild ensures that the last HTML element is always retrieved, regardless of comment nodes in the DOM.
The POS now loads only the Kenyan e-invoicing classification records that are actually used by available products. This avoids pulling unnecessary data into POS sessions, helping improve loading efficiency without changing cashier workflows.
Original PR description
Before `product.unspsc.code` and `l10n_ke_edi_oscu.code` records were loaded without domain, which could lead to loading all records of these models in POS, which is not necessary. This commit adds a domain to the loading of these records, so that only the records that are actually used in the products are loaded in POS.