Thursday, September 17, 2026
68 changes · master
Resolved issues and error corrections
This fixes an issue where saved filter settings could fail to load when their stored text included leading or trailing spaces. The change makes filter handling more tolerant, helping users avoid errors caused by harmless formatting differences.
Original PR description
task-6578010 Forward-Port-Of: odoo/odoo#288643 Forward-Port-Of: odoo/odoo#288528
Sales teams can now use Studio to edit the list view for sales order lines without running into an error. This restores the ability to customize columns and add fields on sales orders, reducing disruption for users configuring their sales workflow.
Original PR description
Before this change: When opening Studio on a Sales Order with existing line items, clicking "Edit List View" on the order lines component triggered a JavaScript error. This prevented users from customizing columns or adding custom fields to the sale order line list view. To reproduce: 1. Open the Sales app and create a new Sales Order with at least one product line. 2. Toggle Studio on. 3. Select the Sale Order Lines list component and click "Edit List View". After this change: Clicking "Edit List View" on sale order lines in Studio works as intended without throwing errors, allowing standard view customizations. opw-6545970 Forward-Port-Of: odoo/odoo#288171
Cancelling an Adyen card payment from the Point of Sale now sends the cancellation to the correct payment request. This prevents payment terminals from continuing to wait for a customer payment after the cashier has cancelled it in Odoo.
Original PR description
Steps to reproduce: - Configure a POS with an Adyen payment terminal - Open the POS, add a product and go to the payment screen - Select the Adyen payment method and click Send - Wait at least 5 seconds - Cancel the payment from the POS - => The terminal keep waiting for the payment (it's not canceled) `_adyenCancel` read `most_recent_service_id` but this value is overwritten by the `_adyenCheckPaymentStatus` polling after 5s, so we try to cancel the wrong payment. We now read the ServiceID from the payment line instead of using `most_recent_service_id`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288874
Vendor bill lists in Accounting now load quickly again after a recent change caused severe slowdowns. The database lookup used to detect duplicate bills was updated so it also covers vendor receipts, restoring the expected performance for users viewing bills.
Original PR description
commit https://github.com/odoo-dev/odoo/commit/391278237dc4fdbf48039bb269f1377d83bbc54d introduced a performance regression.
Go to Accounting > Vendors > Bills
On odoo.com:
| | Time | Query plan |
|--------|--------|--------|
| Before | ~600ms | https://explain.dalibo.com/plan/3ge1afa2aa632be9 |
| Now | 44s | https://explain.dalibo.com/plan/99e847h8d1c38dfd |
After this commit, we're back with the same query plan :)
The reason is the condition `.move_type in ('in_invoice', 'in_refund')`
which was changed to include 'in_receipt':
`.move_type in ('in_invoice', 'in_refund', 'in_receipt')`
Because of that, the query can no longer use the partial index
`_duplicate_bills_idx` because it doesn't include 'in_receipt'.
This commit adapts the index to include moves with type 'in_receipt'.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#288481Fixes French PDP partner lookup so it works when a company endpoint uses a personalized SIREN or SIRET with an added suffix. This helps affected businesses find and validate partners reliably instead of being blocked by overly strict identifier length checks.
Original PR description
In PDP the lookup didn't work if the endpoint is of any length other than 9 or 14 characters, however personalised SIREN/SIRET can have a higher length, this pr fixes that by allowing a SIREN/SIRET suffix in the lookup following the format 'SIRET_SUFFIX' no task id Forward-Port-Of: odoo/odoo#288509
Changing a light user's notification preference to receive messages in Odoo no longer upgrades them to a regular user. This preserves intended access limits while still allowing users to choose their preferred notification method.
Original PR description
Changing the notification preference silently promoted a light user to a regular user, granting them access rights they were never meant to have. Steps to reproduce: - log in as a light user…
Changing the notification preference silently promoted a light user to a regular user, granting them access rights they were never meant to have. Steps to reproduce: - log in as a light user (light/light) - open My Profile - in Preferences, switch "Notification" from "Email" to "Odoo" - log back in as an administrator and open that user's form - the Role field now reads "User" instead of "Light" The notification preference is not a plain field: choosing "Odoo" puts the user in a dedicated technical group. That group grants no access right of its own, but a user is considered light only as long as every group they hold is explicitly known to be a light one. Since this group was never declared as such, it was treated like any ordinary access group, which was enough to have the user reclassified as regular. This commit declares the group as a light one, so the preference stays a preference and no longer affects the user's role. A regression test covers both directions of the toggle for a light and a regular user, checking the role, the underlying group and the role search filter. Note that existing databases need a `mail` upgrade to clear the stale link. Task-6575413 Forward-Port-Of: odoo/odoo#288646
This fixes an error that could appear when users reopened an attendance record from the calendar view. The attendance popover now loads the information it needs to show warnings properly, preventing a disruptive traceback in My Attendances.
Original PR description
Steps to reproduce:- 1. Create an attendance record on calendar view and save it 2. Now try to open that record, and you get traceback `Error: Name 'source_stale' is not defined` Cause:- The "My Attendances" calendar popover shows a stale-source warning banner using invisible="not source_stale" and invisible="source_attendance_id". Both fields were declared at the <calendar> level only, not inside <popover>, so the popover's Card renderer never fetched them, raising error. Fix:- Declare the two fields as direct children of <popover> so their values are included in the popover's record data. task-6577810 Forward-Port-Of: odoo/odoo#288524
This fixes an issue where status steps could incorrectly collapse into a single “More” dropdown when users viewed records at certain browser zoom or display scaling settings. Users on high-resolution screens should now see the full statusbar when there is enough space, making record stages easier to read and navigate.
Original PR description
`areItemsWrapping` decides whether the statusbar buttons fit on one line by comparing `getBoundingClientRect()` heights. Those rects are rounded to physical pixels, so depending on the zoom/DPI ratio…
`areItemsWrapping` decides whether the statusbar buttons fit on one line by comparing `getBoundingClientRect()` heights. Those rects are rounded to physical pixels, so depending on the zoom/DPI ratio a single-line height can come out a fraction of a pixel taller than the reference button height, even though nothing actually wraps. That false positive made the whole statusbar collapse into a single dropdown at some (but not all) browser zoom levels, most noticeable on high-DPI screens where OS scaling and browser zoom combine into non-integer ratios. Steps to reproduce: 1. On a high-DPI screen (e.g. 4K) with OS display scaling enabled. 2. Open any record with a statusbar field (e.g. a CRM opportunity). 3. Set the browser zoom to a value close to 100%. 4. The statusbar collapses into a single "More" dropdown instead of showing every stage inline, even though there is enough room. Round both heights before comparing to ignore that sub-pixel noise while still detecting genuine wrapping. Regression introduced by 7e77b99d2845. task-6545990 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#288194
The Discuss thread header now avoids showing a selection highlight when no action is currently active. This prevents items such as Attachments from appearing selected by mistake, reducing confusion for users.
Original PR description
The `o_switcher` style, shared with the control panel view switcher, renders its sliding background unconditionally and places it from `--SwitchButtons-activeIndex`, which is only set when one of its buttons is active. An action group can have no active action at all: the variable stays unset, `left` falls back to `auto` and the background sits on the first action, making it look selected. This was visible on `Attachments` in the Discuss thread header. Keep the generic switcher style as is and hide that background in ActionList when none of its actions is active. <img width="944" height="534" alt="switcher-before-after" src="https://github.com/user-attachments/assets/914cc215-4ef1-4974-a3e2-432f6be9356c" /> Forward-Port-Of: odoo/odoo#288060
The messaging menu search now uses the same search field design as other Discuss areas. This gives users a clearer focus indicator and more consistent visual feedback when searching messages.
Original PR description
The messaging menu search rolled its own markup, with the border on a wrapper and none on the input, so it had no focus contour or background unlike every other Discuss search. Render SearchInput instead. Its term stays owned by MessagingMenuUIState, whose signal is handed to useSearch(), so there is a single term and nothing to keep in sync. <img width="700" height="548" alt="discuss-search-focus-before-after" src="https://github.com/user-attachments/assets/9150d1ef-dd13-4e66-8cc4-c6dabc140f08" /> Forward-Port-Of: odoo/odoo#288391
This fix prevents sale orders from failing when a user saves immediately after reordering order lines. Odoo now pauses saving while the line reorder action finishes, making the Sales workflow more reliable for quotations and orders with multiple lines.
Original PR description
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has…
When we save a sale order just after reordering its sale order lines, there's a chance that an error is thrown Steps to reproduce: 1. Install Sales 2. Go to Sales and open any quotation that has multiple sale order lines 3. Reorder a sale order line and immediately save (there's more chance to reproduce if you have a lot of sol and if you use the shortcut `ALT + S`) 4. An error is thrown Issue: It is possible that the save takes place during the execution of super.sortDrop. This reassigns the id of all the records in this.props.list.records Therefore, calling `_handleQuantityAdjustment` with the recordMap computed before the save uses an id that has disappeard from this.props.list.records so we cannot find it at https://github.com/odoo/odoo/blob/4973903252865a6a7a2da235bc3a01675dbbff4d/addons/sale_management/static/src/fields/sale_order_line_field/sale_order_line_field.js#L263 which eventually throws an error Solution: Suspend any save mechanism when sortDrop starts and resume it when sortDrop has finished opw-6483206 Forward-Port-Of: odoo/odoo#288370 Forward-Port-Of: odoo/odoo#286787
This fixes an access error that could stop warehouse users from creating backorders during multi-step deliveries when the original sales order belonged to another user. It restores the expected workflow so inventory teams can validate transfers and create backorders without unnecessary sales order permissions.
Original PR description
Multi-step deliveries backorders may create a new picking when processed by a user who only has access to their own sales orders. But, `_key_assign_picking` reads from the related sales order that they don’t have access to. Previously, these moves were confirmed with superuser rights, so this read did not trigger the sales order record rule. Since 19.2, the `sudo()` was removed. The fix would be to add this back in so the access rights error would not be raised. Steps to reproduce on Runbot: 1. Log in as User A (Admin) Turn on Multi-Step Routes Set the warehouse to use 2-step delivery (Pick then Deliver) 2. Create a Sales Order for a product with demand more than stock available and confirm it. 3. Log in as User B with (Demo): Sales: User: Own Documents Only Inventory: User 4. Open the picking transfer generated from User A’s Sales Order. 5. Click Validate and choose Create Backorder. Related: opw-6509032 Forward-Port-Of: odoo/odoo#285778
The website builder now stops a warning timer once style updates finish loading successfully. This prevents misleading warning messages during normal AI website editing and helps keep diagnostics focused on real issues.
Original PR description
Commit [1] made the promise of reloading css bundles race with a timeout promise that logs a warning if CSS reload is not confirmed. However, even if the bundles reloaded on time, the warning was still logged as the timeout was never canceled. [1]: 769ebc02784d2bdebbfb3189e87426994fd87c8f Forward-Port-Of: odoo/enterprise#131722
The marketing automation menu is now hidden when a user is viewing a record that has not been saved yet. This prevents users from trying to add incomplete records to campaigns, reducing confusion and avoiding invalid actions.
Original PR description
This commit fixes an issue with the marketing_automation's new cogMenu. If the form view we are opening is not yet created we have a resId set to False. This is not a normal behavior to try and add a not fully created record to a campaign. Thus we hide the dropdown if there's no resId on the currently opened record. task-6559148 Forward-Port-Of: odoo/enterprise#131828
This fixes where users are sent after archiving or deleting an AI agent. The redirect now uses the correct AI Agent app reference, helping users return to the right place without navigation errors.
Original PR description
Use the ai_agentic namespace when redirecting after archiving or deleting an agent. task-id-6497307 Forward-Port-Of: odoo/enterprise#131833
Field service auto-planning no longer fails when an employee has multiple neighboring shifts at the same time. The system now checks travel time against the furthest relevant previous or next shift, helping schedules generate reliably in more complex planning situations.
Original PR description
This commit fixes a traceback occuring when travel times were checked with the neighboring shifts in the auto-plan. It may be possible that a resource has multiple shifts at the same time, in which case we should use the travel time with the further previous/next shift. task-6579763 Forward-Port-Of: odoo/enterprise#131845
Fixes a crash when exporting the Peruvian "Inventory and Balance" General Ledger report. The report now generates successfully while preserving the required SUNAT file format, preventing disruption for users preparing compliance reports.
Original PR description
### Description of the issue/feature this PR addresses: This PR fixes a server crash in the Peruvian localization (l10n_pe_reports_lib) that occurs when generating the "Inventory and Balance" General…
### Description of the issue/feature this PR addresses: This PR fixes a server crash in the Peruvian localization (l10n_pe_reports_lib) that occurs when generating the "Inventory and Balance" General Ledger report. The crash is triggered by strict validation rules within Python's csv module, which rejects the custom line terminator used to fulfill the SUNAT PLE formatting requirements. ### Current behavior before PR: When a user attempts to generate and export the "Inventory and Balance" report, the server crashes with a ValueError: bad delimiter or lineterminator value. This happens because the csv.DictWriter is initialized with lineterminator='|\n' to ensure every row ends with a pipe. Python's underlying csv implementation rejects this, as it expects standard line endings (\r, \n, or \r\n) and throws an error if the delimiter character (|) is included in the terminator string. ### Desired behavior after PR is merged: The "Inventory and Balance" report generates successfully without server errors. The code now uses the standard lineterminator='\n' to satisfy Python's validation rules. To maintain the mandatory trailing pipe (|) at the end of each row required by SUNAT, a dummy empty column (['']) is appended to the field names with restval=''. This prompts the writer to naturally append the final pipe as a column delimiter before the newline, resulting in the exact |\n output format required, safely and reliably. opw-6509674 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#131302 Forward-Port-Of: odoo/enterprise#129636
This fixes naming and selection issues in marketing automation views introduced by a recent revamp. Users should no longer see crashes or be sent to the wrong screen when opening server actions or trigger forms in campaign flows.
Original PR description
This commit fixes issues that were introduced with the new marketing automation revamp. Some views were either wrongly renamed or no longer used to display server actions or trigger form views in the flow view. Which is an issue as this would either create a crash or open the wrong view entirely. Now the views are correctly renamed and used. task-6559148
Fixed an issue where one-time purchases of recurring products were treated like ongoing subscriptions in stock forecasts. This prevents misleading future demand and helps replenishment planning reflect actual sales commitments.
Original PR description
When a recurring product (with `allow_one_time_sale = True`) is sold as a one-time purchase (no subscription plan), the stock forecast report and replenishment logic incorrectly treat it as an active…
When a recurring product (with `allow_one_time_sale = True`) is sold as a one-time purchase (no subscription plan), the stock forecast report and replenishment logic incorrectly treat it as an active subscription. This results in infinite projected future outgoing moves for standard sales. This occurs because the logic only checks if `recurring_invoice` is True on the product, ignoring whether the parent order actually has a `plan_id`. This commit fixes the issue by: 1. Updating `_get_stock_subscription_lines` in `sale.order.line` to filter out lines using `_subscription_is_one_time_sale()`. 2. Updating the domains in `stock.forecasted_product_product` to require `order_id.plan_id != False` for subscription forecasts, while correctly routing one-time sales (`order_id.plan_id == False`) back to the standard sale domain. 3. Adapting existing tests to verify that one-time sales do not generate future subscription stock forecasts. Task-6193648 Forward-Port-Of: odoo/enterprise#128018 Forward-Port-Of: odoo/enterprise#116889
Vendor bills now keep the manually selected recipient bank account when using Auto-Complete, as long as the bill currency has not actually changed. This prevents accidental payment detail changes for vendors with multiple bank accounts.
Original PR description
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ###…
### Issue: When a bank account is manually set on a bill for a partner with multiple bank accounts, using the Auto-Complete feature could reset the manual selection even without a currency change ### Cause: When `invoice_vendor_bill_id` is set, an onchange assigns `currency_id` unconditionally, even when it is the same value This triggers `_compute_partner_bank_id`, which always recomputes the best matching bank account from scratch without considering the currently set value If the currency did not change, this recompute is unnecessary and silently overrides the manual selection ### Steps to reproduce: - Install `account` - Create a Vendor with 2 bank accounts (keep default values to have equal priority on all accounts) - Create and post a Bill for this vendor with at least one line - Create a new Bill for the same vendor - Set the Recipient Bank to the second account in the list - In Auto-Complete, select the first Bill Before the fix, the Recipient Bank is reset to the first account opw-6210414 Forward-Port-Of: odoo/odoo#288386 Forward-Port-Of: odoo/odoo#283479
Fixes a crash in Odoo Studio when users open the report settings from the cog icon in debug mode. This makes it possible to access the related report configuration form reliably, reducing disruption for users editing reports.
Original PR description
On the report editor in debug mode, click on the cog to open the ir.action.report form view Before this commit, there was a crash After this commit, there is no crash task-6531172
This update improves how text from Odoo templates is prepared for translation by excluding punctuation, icons, and standalone symbols that should not be translated. This helps translators focus on meaningful text, improving translation quality and consistency across several apps without changing core business workflows.
Original PR description
## [FIX] *: better translations in templates This commit aims to provide better translatable strings from static XML templates. To do so, it includes the following changes: - isolated strings that are not meaningful to a translation, such as punctuation or special characters (e.g. "?" for field tooltip marker, "-" to separate tips, or a "x" button to close a panel); - add `t-translation="off"` to strings that are not supposed to end up in translatable strings, such as the aforementioned characters; - a few simplifications for the affected templates have also been applied to the changed nodes when possible, to enforce semantics or to improve readability. - Enterprise: https://github.com/odoo/enterprise/pull/100330 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update improves how text in interface templates is prepared for translation by excluding punctuation, symbols, and other non-meaningful characters. It helps translators focus on useful text, improving translated screens without changing business workflows.
Original PR description
## [FIX] *: better translations in templates This commit aims to provide better translatable strings from static XML templates. To do so, it includes the following changes: - isolated strings that are not meaningful to a translation, such as punctuation or special characters (e.g. "?" for field tooltip marker, "-" to separate tips, or a "x" button to close a panel); - add `t-translation="off"` to strings that are not supposed to end up in translatable strings, such as the aforementioned characters; - a few simplifications for the affected templates have also been applied to the changed nodes when possible, to enforce semantics or to improve readability. - Community: https://github.com/odoo/odoo/pull/236100
The wording for a French e-reporting configuration option was restored because the previous change made its meaning too narrow. This helps users understand that the setting also covers choosing not to send data to the public invoicing portal, reducing confusion during setup.
Original PR description
When we removed the pilot phase setting from the view, we changed that setting to only mean Enable e-reporting. But that's a mistake. In fact people are also choosing not to send to the PPF, so the previous sentence was still right. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288518
This fix ensures that when a past point-of-sale order is later invoiced, the cancellation sent to the Spanish tax authority targets the original simplified receipt instead of the newly created full invoice. This prevents incorrect electronic tax records and helps businesses keep Verifactu POS reporting accurate.
Original PR description
When creating an invoice for a previous POS order, the data sent to AEAT cancels the full invoice instead of the order's simplified invoice. Steps to reproduce: - Open a POS and make a sale without invoicing it; - In the POS, go to the Order tab; - Select the order and fully invoice it. Issue: The AEAT cancellation line added to the pos order actually cancels the full invoice just created [opw-6471927](https://www.odoo.com/odoo/project/49/tasks/6471927) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284277
Fixed a mobile Point of Sale issue where scrolling the product list could accidentally open the product information popup. This prevents interruptions during touchscreen use and makes browsing products smoother for cashiers.
Original PR description
Steps to reproduce: - Open the PoS in mobile mode (touch device) - Swipe the product list up and down a few times Issue: The product info popup sometimes opens while scrolling, as if a product had been long pressed. Cause: Since the product card long press listens to pointerdown/pointerup, a touch that turns into a scroll ends with a pointercancel and never a pointerup, so the long press timer survives the gesture. The debounced onScroll handler is the only other canceller, but when the list is still scrolling from a previous swipe the debounce is already armed, its leading call is skipped and the continuous scroll events keep delaying the trailing call past the long press duration. Fix: Cancel the long press on pointercancel, like pointerup. opw-6514079 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288135 Forward-Port-Of: odoo/odoo#287835
Users can now find and select both service and goods taxes when searching for taxes on product sales or purchase tax fields. This prevents valid tax choices from being hidden and gives businesses more flexibility when configuring product taxes.
Original PR description
With this commit:- - We remove the tax-scope filter from the Search more taxes in the product page's tax fields (Sales taxes and Purchase taxes). - The purpose of doing so is that we should not restrict the user from using service taxes in goods and vice versa. task-6527424 Forward-Port-Of: odoo/odoo#288187
The Mail app now only shows followers who are actually subscribed to receive messages in the recipient list. This prevents users from seeing people listed as recipients when they will not receive the message, reducing confusion in chatter communications.
Original PR description
Before this commit, a follower not subscribed to "Messages" message subtype would still show up in the recipients list (the `To: ` line). This happens since [1] introduced the followers badge on the recipient list, without taking into account the subscription of the followers. This commit fixes the issue by using the `recipientsCount` field, which holds the count of followers subscribed to the "Messages" subtype (except self). [1] https://github.com/odoo/odoo/pull/255498 task-6545679 Forward-Port-Of: odoo/odoo#287214
Colombian Point of Sale orders no longer fail when a company has several DIAN obligation types configured. Receipts can now be generated and printed correctly by listing all applicable obligation descriptions instead of assuming only one exists.
Original PR description
Steps to reproduce: - Colombian company with DIAN electronic invoicing enabled in PoS - On the company contact, set more than one obligation type (e.g. O-13, O-15 and O-23) - Open a PoS session, sell…
Steps to reproduce: - Colombian company with DIAN electronic invoicing enabled in PoS - On the company contact, set more than one obligation type (e.g. O-13, O-15 and O-23) - Open a PoS session, sell a product and pay Issue: The order fails to sync with "Expected singleton: l10n_co_edi.type_code(x, y, z)" as soon as the DIAN document is accepted, and the receipt cannot be printed. On 18.0 to saas-19.1 the same crash happens when the receipt data is generated for printing. Cause: `_compute_l10n_co_edi_pos_receipt_data` fills `obligation_type_description` by reading `description` directly on `l10n_co_edi_obligation_type_ids`, which is a many2many. The read only works when the company carries exactly one obligation type, while a Colombian company commonly has several (they are all sent to the DIAN in `TaxLevelCode`). Fix: Join the descriptions of all obligation types, the same way the DIAN invoice PDF report already does. opw-6576523 Forward-Port-Of: odoo/enterprise#131747
Long bill reference text in outstanding credit or debit sections is now shortened visually so it stays within the page layout. This keeps Credit Notes and Vendor Bills easier to read and prevents confusing display issues when references are unusually long.
Original PR description
The "Outstanding credits" or "Outstanding debits" sections of a Credit Note or Vendor Bill will overflow when the "Bill Reference" is too long. We resolve this by applying the text-truncate class.…
The "Outstanding credits" or "Outstanding debits" sections of a Credit Note or Vendor Bill will overflow when the "Bill Reference" is too long. We resolve this by applying the text-truncate class. Steps to Reproduce: 1. Create a new 19.0 db and load demo data. 2. Accounting -> Vendors -> Refunds -> RBILL/2026/09/0001 3. Click the entry in the Outstanding credits section. 4. Enter a long "Bill Reference" value, e.g. asdf asdfasfasdfasdfasdfasdfasdfasdfasdfasdfasdf. 5. Go back to the Credit Note and observe the text overflow. opw-6558982 <img width="1254" height="1162" alt="bill_reference_long" src="https://github.com/user-attachments/assets/8c762b50-65a8-44bf-9a28-bd34887d5928" /> <img width="1620" height="1294" alt="overflow" src="https://github.com/user-attachments/assets/f5c47404-fb7f-4715-8815-cabe5dda3805" /> <img width="1586" height="1159" alt="truncated" src="https://github.com/user-attachments/assets/2a80f656-0a12-4805-9c1d-fd20379655ce" /> Forward-Port-Of: odoo/odoo#288389
GCC Arabic-English invoice PDFs no longer fail when an invoice includes section or note lines. This prevents internal server errors during invoice preview or printing, making invoice generation more reliable for affected businesses.
Original PR description
## Problem When rendering PDF invoices that contain **section** or **note** lines, the `l10n_gcc_invoice.arabic_english_invoice` QWeb template raises: ``` TypeError: argument of type 'bool' is not…
## Problem When rendering PDF invoices that contain **section** or **note** lines, the `l10n_gcc_invoice.arabic_english_invoice` QWeb template raises: ``` TypeError: argument of type 'bool' is not iterable ``` This happens because `account.move.line` records of type `line_section` or `line_note` have `name = False`. The template evaluates `arabic_name not in line.name` (and the same for `english_name`), which fails because Python cannot apply the `in` operator on a boolean value. ## Fix Add a `line.name and` guard before each `not in` check: ```xml <!-- Before --> <span t-if="arabic_name not in line.name" .../> <span t-if="(english_name != arabic_name) and (english_name not in line.name)" .../> <!-- After --> <span t-if="line.name and arabic_name not in line.name" .../> <span t-if="line.name and (english_name != arabic_name) and (english_name not in line.name)" .../> ``` ## Steps to reproduce 1. Install `l10n_gcc_invoice` on an Odoo 16.0 instance. 2. Create a customer invoice and add a **Section** line. 3. Print/preview the invoice PDF. 4. Observe `Internal Server Error` / `TypeError: argument of type 'bool' is not iterable`. Forward-Port-Of: odoo/odoo#278887 Forward-Port-Of: odoo/odoo#267147
This fix prevents Argentina electronic invoices from sending zero-value VAT details when advance payments fully offset the invoice. It helps $0 final invoices pass ARCA validation instead of being rejected, supporting the standard 100% down payment workflow.
Original PR description
## Description of the issue When an Argentinian invoice contains advance-payment deduction lines that exactly cancel the product lines (net taxable base = 0 for a given VAT aliquot), the invoice is…
## Description of the issue
When an Argentinian invoice contains advance-payment deduction lines that exactly cancel the product lines (net taxable base = 0 for a given VAT aliquot), the invoice is rejected by the ARCA (AFIP) WSFE web service with:
> **Error 10018**: "Si ImpIva es igual a 0 el objeto Iva y AlicIva son obligatorios. Id iva = 3 (iva 0)"
This is the standard "100% down payment" flow: the customer is invoiced an advance for the full amount, and the final invoice deducts that advance, resulting in a $0 invoice that must still be validated against ARCA.
This is a forward-port to 19.0 of #270846 (same fix, targeted at 18.0, closed unmerged). The bug is still present in 19.0: `_get_vat()` in `addons/l10n_ar/models/account_move.py` evaluates its filter on the raw unrounded aggregated floats.
## Steps to reproduce
1. On a company with the Argentinian localization (`l10n_ar_edi`) configured for electronic invoicing (WSFE), create a sale order with one or more product lines taxed at IVA 21% (e.g. total $121,000).
2. Create a **down payment invoice for 100%** of the order and validate it against ARCA (this one succeeds).
3. Create the final invoice from the sale order: it contains the product lines (positive) and the down-payment deduction line (negative), both at IVA 21%. Total to pay: **$0.00**.
4. Confirm the invoice and send it to ARCA.
5. **Current behavior (bug):** ARCA rejects the request with error 10018. Inspecting the generated WSFE request shows `ImpNeto=0.0`, `ImpIVA=0.0`, `ImpTotal=0.0` and an `Iva` block containing an all-zero aliquot, e.g. `{'AlicIva': [{'Id': '5', 'BaseImp': 0.0, 'Importe': 0.0}]}` — instead of `Iva: null`.
6. **Expected behavior (after fix):** no zero-amount aliquot is sent (`Iva` is `null`) and ARCA approves the $0 invoice.
## Root cause
In `_get_vat()`, the positive product lines and the negative down-payment deduction line share the same VAT aliquot, so the aggregation by `vat_afip_code` nets the group to zero. However, floating-point accumulation in the aggregated tax details leaves a tiny residual (~1e-12) in `base_amount_currency` / `tax_amount_currency`. The filter condition checks the **raw unrounded** values:
```python
if grouping_key['vat_afip_code'] not in (False, '0', '1', '2') and (values['base_amount_currency'] or values['tax_amount_currency']):
```
The ~1e-12 residual is truthy in Python, so the aliquot entry is kept — even though both `BaseImp` and `Importe` are rounded to `0.00` two lines below when building the entry. The WSFE request therefore carries a non-null `Iva` block with all-zero amounts, which ARCA rejects with error 10018.
## Fix
Round `BaseImp` and `Importe` to 2 decimals **before** evaluating the filter condition, so an aliquot whose amounts cancel out is excluded from the `Iva` array (the same rounded values are then reused when building the entry, keeping the sent amounts unchanged for every other case):
```python
base_imp = float_round(amount_sign * values['base_amount_currency'], precision_digits=2)
importe = float_round(amount_sign * values['tax_amount_currency'], precision_digits=2)
if grouping_key['vat_afip_code'] not in (False, '0', '1', '2') and (base_imp or importe):
```
Behavior is unchanged for every invoice whose aliquots round to a non-zero base or tax amount.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#286005Vehicle imports now better understand the expected brand/model format when creating vehicle model records. This helps manually created fleet vehicles import more reliably and reduces avoidable errors during data migration or updates.
Original PR description
The name has a specific format `<brand>/<model>`, hence the fix overwrites the `name_create` function called when the import tries to create new model records, so that the name passed to that function can be correctly interpreted. Errors will occur for vehicles from the demo data (because of their external ID) but should work for any vehicle created manually. task-6578351
Fixes an issue where editing certain Kanban cards in Odoo Studio, such as Project tasks, could fail when adding or removing fields. This lets users customize those views reliably without save errors, while leaving other views unchanged.
Original PR description
Issue: Editing the Project task Kanban with Studio fails with an "element cannot be located in parent view" error. This affects Kanban views whose card architecture is provided through `card_id`.…
Issue: Editing the Project task Kanban with Studio fails with an "element cannot be located in parent view" error. This affects Kanban views whose card architecture is provided through `card_id`. Adding or removing a field produces an XPath targeting the inlined `<card>`, but that node cannot be found when the Studio customization is saved. Steps to reproduce: * Open Project > Tasks > My Tasks in Kanban view. * Open Studio. * Add or remove a field from the card. Cause: The client receives a postprocessed Kanban architecture in which the view referenced by `card_id` has already been appended as a `<card>` node: https://github.com/odoo/odoo/blob/1aa1f1967c7b9c8fd2c941fbc0c7b4c563698e46/odoo/addons/base/models/ir_ui_view.py#L3138-L3140 Studio therefore generates paths containing `/kanban/card`. However, Studio normalization applies those paths to the pre-postprocessed architecture, which still contains only the `card_id` attribute: https://github.com/odoo/enterprise/blob/42aa8fafdef159476d708f91467cba6f7fb2c6d3/web_studio/models/ir_ui_view.py#L667-L671 As `<card>` does not exist in that source tree, the inheritance engine cannot locate the target. Solution: We need to inline the referenced card before applying or normalizing Studio customization specifications. This makes Studio operate on the same architecture shape that was presented to the client. The `card_id` attribute is then removed from that temporary source to prevent regular post processing from appending the card a second time. The behavior is limited to Studio customization views and is a no op for Kanban views without `card_id`, preserving the existing inheritance flow for other views. opw-6445398 Forward-Port-Of: odoo/enterprise#127393
This change restores the previous way Mexican electronic payment complements calculate amounts, following updated guidance from the certification provider after consultation with the government. It helps reduce compliance and validation issues by using the maximum allowed decimal precision for payment amounts.
Original PR description
Quadrum reverted their changes because > Derived from a consultation with the government we reverted to our previous behavior, we recommend using the maximum number of decimals allowed Reverts commit https://github.com/odoo-dev/enterprise/commit/f13d204dacf9eae98c78de26e9f2e54387a0eaee as well opw-6561617 Forward-Port-Of: odoo/enterprise#131640 Forward-Port-Of: odoo/enterprise#131581
Payroll version pages now display the full details for employee-related warnings instead of omitting them. This helps payroll teams understand and resolve employee issues without missing important context.
Original PR description
`_compute_issues()` looked up `warning_details` using `version` keys for warnings keyed by `hr.employee`, dropping the issue details. Use `version.employee_id` as the lookup key when `warning.model_name` is `'hr.employee'`. Task: 6483048
Fixes a VoIP call flow editor issue that prevented users from moving an existing connection to a new destination. This helps teams update call routing flows without losing connectors or being blocked by connection limits.
Original PR description
An output port that already has a connection couldn't be rewired to a new target: grabbing it looked for another output port instead of an input port, so the old connector was removed and never replaced. Dropping a new connection onto an output port that was already at its connection limit was rejected outright instead of replacing the existing connection.
This update adjusts HR forms so structure type information is not hidden where it is still needed. It helps preserve clarity for users managing employees and contract templates while avoiding an unintended form change.
Original PR description
- hide `structure_type_id` on employee and contract template form views task-6569952 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix makes Belgian payroll time off allocations more consistent and accurate, especially when employees have multiple contract changes or working schedule updates. It also improves the schedule change process and adds clearer explanations in the interface so payroll teams can better understand allocation values.
Original PR description
Time off allocation fixes:
- Fixed rounding of time off allocations: some parts of the code rounded to full days, while others rounded to half-days.
- Fixed the calculation of time off from holiday attestations, which was done differently in different parts of the code.
- Fixed allocation calculations for employees with multiple contract versions, ensuring that each version is only taken into account for its actual effective period.
- Fixed the Working Schedule Change wizard:
-- allocations were not found when the work entry types had the same code but different records (generic vs. Belgian);
-- the calculated allocation was not correctly displayed in the wizard;
-- fixed the allocation update for working schedule changes starting in the future.
- Added a tooltip to explain the time off allocation values in the UI.
task: 6452166This update fixes cases where some screens could behave as if the user was not on a small device, which could affect mobile layouts in areas like accounting, imports, mail, and navigation. It also adds safeguards so outdated internal references fail visibly during testing instead of causing quiet display issues later.
Original PR description
Removes depracated `env.isSmall` and `env.debug` and make it throw if used (to prevent forward port mistakes) Enterprise PR: https://github.com/odoo/enterprise/pull/130698
EU OSS sales are now reported correctly in French PDP Flow 10 by excluding destination-country VAT from French VAT rate checks. This keeps the invoice and accounting VAT intact while reporting the taxable amount in the appropriate non-French VAT category, reducing reporting rejections.
Original PR description
OSS sales are taxed in the customer's Member State but are not subject to French VAT. They must therefore be reported under TNT1, while the Flow 10 Schematron only accepts French VAT rates. Identify taxes generated for the EU OSS scheme through their OSS tag. Keep the destination VAT on the invoice and in accounting, but report the taxable base under TNT1 with a zero tax rate and amount. Continue rejecting unsupported rates for regular taxes and invalid OSS rates. no task id Forward-Port-Of: odoo/odoo#288013
This update removes redundant code in the web test mock server that had no effect on behavior. It helps keep the codebase cleaner and easier to maintain without changing any user-facing functionality.
Original PR description
`record[fieldName] = record[fieldName]` does nothing. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Spreadsheet actions now preserve approved rich formatting in help messages instead of showing it as escaped plain text. This ensures users see action guidance as intended while keeping existing safeguards for missing action details.
Original PR description
Current behavior before PR: - `navigateTo` cleans up the action description using `JSON.parse(JSON.stringify(...))`. - This removes Owl's `markup()` wrapper from the `help` field. - As a result, the trusted HTML is converted to a plain string and gets escaped instead of being rendered. Desired behavior after PR is merged: - Pass the action description directly to doAction. - `_preprocessAction` already provides defensive fallbacks for individual fields, such as `action.domain || [] and action.display_name || action.name || "".` - Therefore, undefined fields or missing keys are handled safely without the need for the JSON round-trip. - This preserves the trusted markup in the help field and renders the HTML correctly. Task: [6428217](https://www.odoo.com/odoo/project/2328/tasks/6428217) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286191
This fix prevents an error from appearing when a user clicks a shared Sign document link while still editing a website page. It improves the website editing experience by safely handling pages that do not have the usual editable record information.
Original PR description
# How to reproduce - Go to Sign > Templates - Upload a PDF & click on Share - Copy the link - Go to a page with a EditInBackend systray item (e.g. a Product or Event page) - In the editor, add the…
# How to reproduce - Go to Sign > Templates - Upload a PDF & click on Share - Copy the link - Go to a page with a EditInBackend systray item (e.g. a Product or Event page) - In the editor, add the copied link to a button or some text - Save - While still in editor mode, click the link # The issue A traceback is shown # Cause The traceback is caused by the call to this function : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/services/website_service.js#L336 In our case, `this.currentWebsite.metadata.mainObject` is undefined, so trying to access `.model` throws. `mainObject` is undefined because the sign link opens an XML file, which does not have any metadata associated to it : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/services/website_service.js#L150-L155 The call to `getUserModelName` is done by the `EditInBackendSystrayItem` component which subscribes to the "CONTENT-UPDATED" event : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/edit_in_backend.js#L33 However, this method should not be called by the bus because the sign page does not have this systray item. The issue is, the display of the component is managed by the `WebsiteSystrayItem`, based on the `hasEditableRecordInBackend` getter : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/website_systray_item.js#L10 https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/client_actions/website_preview/website_systray_item.xml#L9 And the re-render of that component that would remove the `EditInBackendSystrayItem` component is triggered by a call to `renderAndAdapt`, which is also subscribed to "CONTENT-UPDATED" : https://github.com/odoo/odoo/blob/f8c29412e71af098b2949f485a8011b01b64b368/addons/website/static/src/components/navbar/navbar.js#L48 So the destroy of the `EditInBackendSystrayItem`, which should remove the listener that calls `getUserModelName` is trigerred AFTER the call to that function is already done opw-6443794 Forward-Port-Of: odoo/odoo#281763
This fixes an issue where clearing an embedded code snippet on a website page did not persist after saving, causing the old embed to reappear on reload. Empty embeds are now properly removed, so editors see the expected empty-content message instead of stale content.
Original PR description
Scenario: - drop embedded code snippet - edit it to add a value - edit it to put it empty - save Result: on reload the embed is not removed and the old value is restored In 18.2, setting it empty would work and you would see an info alert: "Your Embed Code snippet doesn't have anything to display. Click on Edit to modify it." Fix: delete the embed field if it is saved empty. opw-5454289 Forward-Port-Of: odoo/odoo#251537
This fixes an intermittent issue in Point of Sale automated checks where receipt printing failure scenarios could move ahead too quickly on busy systems. The change makes these checks more stable, reducing false failures in validation pipelines without changing customer-facing POS behavior.
Original PR description
The fast-payment tours with automatic receipt printing configure an unreachable printer to exercise the printing-failure path. Once the failed print settles, FeedbackScreen arms a 1500ms timer that auto-navigates to the next order (iface_print_auto). The tour needs to detect the resulting error dialog, confirm it, then click the validation button, all before that timer fires. On a fast machine this comfortably fits, but on a loaded CI runner the sequence can take longer than 1500ms, so the auto-navigation happens first, unmounting the feedback screen before the tour can click ".button.validation" and causing a step timeout that could not be reproduced locally. Click on the feedback screen background right after confirming the dialog to call stopAutomaticSkip() and cancel the pending timer, removing the race entirely. This mirrors the pattern already used in test_automatic_receipt_printing. runbot-946191 Forward-Port-Of: odoo/odoo#288593 Forward-Port-Of: odoo/odoo#284690
This update fixes screens and menus that could show the wrong layout on phones or hide certain options because they were checking outdated system values. It improves reliability for mobile users and restores expected menu behavior in apps such as Accounting, Documents, Appointments, Spreadsheets, ESG, and Time Off.
Original PR description
Removes depracated `env.isSmall` and `env.debug` and make it throw if used (to prevent forward port mistakes) Community PR: https://github.com/odoo/odoo/pull/287002
Belgian payroll now applies the correct train pass reimbursement rate for employees under Joint Committee 302 from February 2026. This prevents employees from being under-reimbursed because the sector table values already include the legally required calculation.
Original PR description
Previously, the system was applying an additional 80% reduction ratio on top of the CP 302 train allowance values. However, the rates listed in the official CP 302 sectoral table already incorporate the legally applicable 71.8% calculation. Applying an extra 80% factor resulted in an under-reimbursement of train transport costs for employees under Joint Committee 302. **What:** - Added the missing rule parameter value record _`rule_parameter_cp302_train_reimbursement_ratio_2026`_ setting the ratio factor to 1 (100%) effective from February 1, 2026. task-6532036 Forward-Port-Of: odoo/enterprise#131583 Forward-Port-Of: odoo/enterprise#130291
This fix prevents users from opening additional shop floor menu dialogs while a manufacturing order is already loading. It avoids an error that could appear on slower connections, making shop floor navigation more reliable for manufacturing users.
Original PR description
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. *…
**Steps to reproduce:** * Install the **Manufacturing** module with **Work Orders** enabled. * Create and confirm a Manufacturing Order with at least one Work Order. * Open the **Shop Floor** view. * On a work order card, click the **gear** icon to open the menu dialog. * Click **Open Manufacturing Order** on a slow network connection. * Before the MO form view finishes loading, quickly click the **gear** icon again and open another dialog (e.g. Log Note). * The MO form view loads, destroying the shop floor component. * Close the Log Note dialog. **Observed behavior:** * An `UncaughtPromiseError: Component is destroyed` error is thrown because the dialog tries to interact with the shop floor component that has already been destroyed by the navigation to the MO form view. **Cause:** * When the user clicks "Open Manufacturing Order", `doAction` is called to navigate to the MO form view, and `props.close()` immediately closes the menu dialog. However, the shop floor component is still visible while the new view is loading. * During this gap, the gear button remains clickable. If the user opens another dialog (e.g. Log Note), that dialog holds a reference to the shop floor component. When the MO form view finishes mounting, the shop floor is destroyed, and closing the stale dialog triggers operations on the destroyed component. **Fix:** * Add an `actionPending` state flag to `MrpDisplayRecord`. When the user selects "Open Manufacturing Order" from the menu dialog, an `onSelect` callback sets `actionPending` to `true`, which disables the gear button and prevents any new dialog from being opened. * The flag is only set for `openMO` (which navigates away and destroys the component), not for other menu actions like Scrap, Add Component, or Log Note which open wizard dialogs and return to the shop floor. opw-6107579 Forward-Port-Of: odoo/enterprise#131538 Forward-Port-Of: odoo/enterprise#123490
The Norwegian eVAT report now lists tax code details in a consistent order every time it is generated. This prevents random test failures and helps ensure the report output remains reliable and predictable.
Original PR description
The Norwegian tax report is built from ordered elements, but the summary detail per tax code is appended from a list that is quasi-directly calculated straight from PostgreSQL. The query does not request a specific result order causing indeterminism (it depends on the query plan chosen: hash vs. sort aggregate, parallel workers) when the whole XML tree is compared against a golden copy in tests. An explicit ORDER BY clause is added to the taxes query. The chosen key is the tax_code, because these can be casted for integer natural sort. The produced XML tree can be compared in its entirety without random failures. REF Runbot; https://runbot.odoo.com/odoo/error/939532 Forward-Port-Of: odoo/enterprise#131702 Forward-Port-Of: odoo/enterprise#131307
This fix ensures rental orders keep track of serial numbers when pickups and returns are handled through stock transfers. It prevents the return wizard from opening without available serial numbers after a partial return, allowing staff to complete subsequent rental returns reliably.
Original PR description
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return…
**Issue** When rental transfers are enabled and rental pickups/returns are processed through stock pickings, it may become impossible to perform a subsequent rental return through the rental return wizard. **Steps to reproduce** - Activate "Rental Transfers" in the settings - Create a rental product P, tracked by serial number - Create two serial numbers for P - Create and confirm a rental order for 2 units of P - Validate the pickup transfer - Partially validate the return transfer without creating a backorder - Open the rental order and click on "Return" -> The return wizard opens without any available serial number and validation fails with a serial number-related error. **Cause** When clicking on "Return", if there is no pending pickup/return transfer: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/models/sale_order.py#L62-L68 the rental return wizard is opened directly: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/models/sale_order.py#L316 No serial number is prefilled in the wizard because `returned_lot_ids` is empty: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L122-L124 This is because `returnable_lot_ids` is empty as well. `returnable_lot_ids` is computed while generating the wizard lines: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L38 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_renting/wizard/rental_processing.py#L47-L48 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L99-L106 and `returnable_lots` is empty because both `pickedup_lots` and `returned_lots` are. Those fields are currently only populated through the rental wizard flow: https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L42-L43 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L160-L161 https://github.com/odoo/enterprise/blob/d1ba2417affb81c4351ab9f86bc0a6ad5ceb8caf/sale_stock_renting/wizard/rental_processing.py#L166-L167 Since this flow uses stock pickings instead of the rental wizard, those fields are never updated, preventing the wizard from determining any returnable serial number. opw-6150305 Forward-Port-Of: odoo/enterprise#127590 Forward-Port-Of: odoo/enterprise#119257
Swiss payroll users can now save draft hourly payslips without losing a manually entered wage factor. This prevents incorrect resets to zero and reduces the need to re-enter payroll data.
Original PR description
**Steps to reproduce:** 1. Create a draft Swiss ELM payslip for an hourly-paid employee with no automatic hourly work-entry/input 2. In the Wages tab, manually update the `Factor` (`rate`) field of the `Hourly Salary` line 3. Save the payslip **Issue:** The manually entered `Factor` is reset to `0.00` **Cause:** - `l10n_ch_swiss_wage_ids` is a stored computed field without explicit `readonly=False`, causing manual modifications to the line values to be discarded during field recomputation on save. opw-6536243 Forward-Port-Of: odoo/enterprise#131636 Forward-Port-Of: odoo/enterprise#130824
Updates to employee working schedules now create clearer leave allocation messages. The message correctly shows the related contract and includes the details of what changed, helping HR teams understand and audit schedule updates more easily.
Original PR description
When modifying an employee's working schedule via the wizard, the logged chatter message on the leave allocation incorrectly evaluated the contract name to "False" and lacked details on the changes made. This PR fixes the problem by calculating and logging the necessary details regarding the changes.
Belgian payroll now correctly handles the Special Social Contribution when generating a 13th month payslip. If there is no regular monthly payslip for the same period, the contribution is set to zero, helping avoid incorrect payroll deductions.
Original PR description
When we generate a 13th month payslip, we need to check if there is a monthly pay payslip in the same period. If not, the Special Social Contribution will be 0. task-6512347
The Nilvera e-invoice integration now keeps the amount-in-words note fully in Turkish when invoices use a foreign currency. This avoids mixed-language wording such as English currency subunits appearing in Turkish e-invoices, helping keep documents compliant and clear.
Original PR description
### Issue before this commit: When generating a Nilvera e-invoice in a foreign currency (e.g., EUR), the amount written in words inside the <cbc:Note> tag contained a mix of languages. While the…
### Issue before this commit: When generating a Nilvera e-invoice in a foreign currency (e.g., EUR), the amount written in words inside the <cbc:Note> tag contained a mix of languages. While the numbers were correctly translated to Turkish, the currency subunit label was fetched using the customer's language. This resulted in a partially translated string (like "... SIFIR CENTS") instead of the expected fully Turkish text (like "... SIFIR SENT"). ### Steps to reproduce the issue: 1. Download Accounting and l10n_tr_nilvera_einvoice 2. Create an API KEY: https://docs.google.com/document/d/1EUzvTBnSm9-VwIfBsX299MHGXIVys-uijnsJ1fpz7vI/edit?tab=t.0#heading=h.e6i8a29lff5t 3. Go to a turkish client on the Accounting tab and click on 'Verify' for the Nilvera status 4. Go to currencies and activate EUR (be sure there is also the translation for currency subunit) 5. Go to invoices, create one for the Turkish customer you already verified setting the currency as EUR and send it with Nilvera 6. See that current output is <cbc:Note>YALNIZ : BEŞYÜZDÖRT EUR SIFIR CENTS</cbc:Note> (Turkish numbers with English subunit) but the expected output is <cbc:Note>YALNIZ : BEŞYÜZDÖRT EUR SIFIR SENT</cbc:Note> (Fully Turkish text) ### Cause of the issue: The issue occurs because the currency_subunit_label field is not translated but fetched using the language of the customer in the invoice. ### Reason to introduce the fix: To ensure that the amount in words inside the <cbc:Note> tag is completely formatted in Turkish, complying with Nilvera and local e-invoicing requirements, regardless of the customer language. opw-6523794 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288122 Forward-Port-Of: odoo/odoo#287630
Italian point-of-sale refunds can now be processed from a different trusted POS without receipt printing failures. The system keeps the original printer details with the order, so refund receipts use the correct fiscal printer information.
Original PR description
Steps to reproduce: - Set up two POS configurations and add each to "Trusted POS"; - Connect a different fiscal printer to each POS configuration; - Process an order on POS A; - Refund that order on POS B. **Issue**: The refund receipt fails to print. The system currently transmits the serial number of the active POS configuration's printer instead of the printer that processed the original order. As a result, POS B's printer receives its own serial number alongside order identifiers that do not exist in its local fiscal memory. **Solution**: Store the processing printer's serial number directly on the `pos_order model` to ensure the correct serial number is transmitted during cross-POS refunds. [opw-6499079](https://www.odoo.com/odoo/project/49/tasks/6499079)
The add-to-cart notification now correctly shows loyalty reward progress again when shoppers add eligible products to their cart. This helps customers see their discount or loyalty progress at the right moment, reducing confusion during checkout.
Original PR description
Versions -------- - master Steps ----- 1. Install eCommerce and Discounts & Loyalty (demo data). 2. On the shop, add a Furniture product to the cart. Issue ----- No progress bar in the add to cart notification. Cause ----- The patch on `ItemAddedNotification` was not migrated along bb606bbe6330 and still declares its prop through the static `props`, which Owl no longer reads. Solution -------- Declare the prop through its own `useProps` call in a patched `setup`, and read it from `this.loyaltyProps` in the template. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Rounded point-of-sale payments are now recorded correctly even when the stock app is not installed. This prevents accounting imbalances when closing PoS sessions, reducing disruption for retailers using cash rounding.
Original PR description
Before this commit: = - The rounding move line creation was moved from point_of_sale to pos_stock while removing the dependency of stock on point_of_sale. - As a result, when pos_stock was not installed, no rounding move lines were created for rounded PoS payments, leading to unbalanced journal entries during session closing. After this commit: = - Restored the rounding move line creation in point_of_sale so that rounded payments are correctly handled. task-6214240 runbot-error-242920 Forward-Port-Of: odoo/odoo#264288
Long product names on smaller printed labels can now wrap onto a new line instead of being cut off with an ellipsis. This makes printed labels easier to read and keeps label behavior consistent with the previous version.
Original PR description
In 19.0, long names wrap to a newline, while in masters everything is clipped to one line with ellipsis. This commit will increase the height for title fields on smaller labels so they behave the same as on 19.0 and can still wrap --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Installing Fleet Stock directly now also enables the required batch transfer access for internal users. This prevents the settings page from accidentally triggering a Fleet Stock uninstallation prompt, making setup safer and smoother.
Original PR description
If stock_fleet is installed directly without enabling batch transfers beforehand, stock.group_stock_picking_batch is not enabled for internal users. When opening the settings, the onchange on group_stock_picking_batch unchecks module_stock_fleet, and saving triggers the uninstallation wizard of stock_fleet. This commit fixes the issue by enabling stock.group_stock_picking_batch for base.group_user in the post_init_hook of stock_fleet. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
AI agents now manage their URL-based attachments more reliably, so each agent keeps the right linked content separate from others. This helps prevent mix-ups between agents and supports smoother background processing of URL content.
Original PR description
Many2one URL attachments' fixes to ensure each agent has its own URL attachments.
Point of Sale now avoids errors when opening a session if the browser has old cached data for models that were renamed or removed. This helps users resume POS work without needing a manual data reload after module changes or upgrades.
Original PR description
In PR-#[225341](https://github.com/odoo/odoo/pull/225341) we started passing all the models which are cached on the front end directly to the back end, but if the database existed before and the front end cached models which no longer exist, either because the model name changes (such as pos.product.template.snooze -> pos.snooze), or because a module was uninstalled (removing pos_restaurant_appointment), the front end would ask the back end for models which no longer exist, and that would error. When we do the reload data, all the local cache would be deleted and then we could launch the POS. To fix it, now the back end will check whether the model exists before trying to filter on it, and just ignore it if it doesn't exist Task-[6562705](https://www.odoo.com/odoo/project/1737/tasks/6562705) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Inter-company purchase receipts are no longer marked as already picked when they are created from a confirmed sales order. This lets warehouse teams process the receipt normally in the Barcode app and avoids confusion or skipped handling steps.
Original PR description
Issue ----- When confirming a SO, the corresponding PO picking should not have its' MLs set as `picked` to allow treating the transfer in the barcode app. Steps to reproduce ----- - Create 2 companies A & B - Settings > Inter-Company Transactions - Create Purchase Orders - Set the created PO to be "Validated" by default - Create a SO from company A to B - Validate the OUT picking in company A - Open the PO in company B - Go to its' picking and open it in barcode > The line is already picked ----- Ticket: opw-6481828 Forward-Port-Of: odoo/enterprise#131391
The Austrian point-of-sale setup test data now uses the updated currency reference. This keeps automated checks aligned with the latest shared currency data and helps prevent false failures during validation.
Original PR description
In this commit: ------- - Update the currency ID to 2 when creating the PoS configuration for the Austrian localization, reflecting the corresponding currency data change in the related PR. Task-6576886
After archiving or deleting an AI agent, users are now sent to the correct agent page. This prevents a broken or incorrect navigation path and keeps agent management workflows smooth.
Original PR description
Use the ai_agentic namespace when redirecting after archiving or deleting an agent. task-id-6497307
Odoo no longer crashes when a user clicks an embedded file link whose attachment has since been deleted. Instead, the editor handles the missing file safely, keeping records with HTML fields usable even when old links are stale.
Original PR description
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project…
Clicking a stale /web/content/<id> link in an HTML field crashed the client after the related attachment had been deleted. **Steps to reproduce:** 1. Open any record with an HTML field (e.g. Project > Task description). 2. Upload a file into the HTML field to embed an attachment link. 3. Save the record. 4. Delete the uploaded attachment from Chatter > Files, or from Settings > Technical > Attachments. 5. Reopen the record and click the embedded file link. **Client Error:** `TypeError: Cannot destructure property 'mimetype' of '(intermediate value)' as it is undefined at LinkPopover.loadAsyncLinkPreview` `TypeError: Cannot destructure property 'type' of '(intermediate value)' as it is undefined at LinkPopover.updateDocumentState` When the attachment is missing, ormService.read returns an empty array, so fetchAttachmentMetaData returned undefined instead of entering its catch block. LinkPopover then crashed while destructuring that result in loadAsyncLinkPreview and updateDocumentState. Return a safe fallback metadata object when the attachment cannot be found so both code paths keep working without crashing. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279281
New Singapore companies will now be created with the correct accounting configuration for inventory purchases. This ensures price differences between product cost and purchase price are posted to the expected account, improving the accuracy of vendor bills and stock valuation.
Original PR description
Singaporean companies didn't have the anglo saxon accounting enabled. Price difference account was then not hit when buying a product with a different price than the one in the product page. Steps to reproduce: ------------------- * Create a product P * Set the costing method to "Standard Price" and the inventory valuation to "Perpetual (automated)" * Make sure a price difference account is set in the product category * Create a RFQ for P and set a different price than the one in the product page * Confirm the RFQ and receive the product * Create a vendor bill for the RFQ and validate it > Observation: If you check the lines in the bill there is no price difference account hit. Why the fix: ------------ We set anglo saxon accounting to True so that all new companies have the correct setup. opw-6525817 Forward-Port-Of: odoo/odoo#288261
This fixes a display issue in Discuss call settings where the selected speaker could be shown with the microphone name when Chrome reports matching default device IDs. Users now see the correct device name in the dropdown, reducing confusion when choosing audio devices for calls.
Original PR description
Steps to reproduce: - Have an input audio device and an output audio device with different names but same device ID. Using Chrome, if the OS only sees one of each, both should have "default" as device ID. (alternatively, modify the code at `updateDevicesList` to simulate having devices of that kind). - Select those devices in the call settings UI, then open the settings UI dropdown again. => The "input" device is properly shown but the "output" device shows the "input" device names (while in fact this is the right one selected in the inner dropdown). This happens since [1]. Before that there were native `<select>` nodes that filtered devices by kind before rendering each option, and the "default" value of Chrome was not really handled. [1]: https://github.com/odoo/odoo/commit/93d0931fba1f467de265200b6a0463cf7edf9534 Related to task-6533808 Forward-Port-Of: odoo/odoo#288537 Forward-Port-Of: odoo/odoo#288285