Daily updates from Odoo
Wednesday, August 5, 2026
54 changes · saas-19.3
Resolved issues and error corrections
The Helpdesk unanswered filter now treats automatic acknowledgement emails as already answered. This prevents newly created website tickets from being incorrectly flagged as waiting for a customer response, helping teams focus on real unanswered messages.
Original PR description
Steps to reproduce: --------- - install website_helpdesk - set an email address on the company partner if it is empty ( it is empty in a database without demo data). - generate a ticket from the website. - apply the Unanswered filter. Issue: ------ system generated acknowledgement message is considered an unanswered customer reply. Fix: -------- system generated acknowledgement messages are now considered answered. task-5138678 Forward-Port-Of: odoo/enterprise#125977
Businesses using Avalara Brazil can now confirm multiple customer invoices at once without the process failing. This prevents validation interruptions and supports smoother batch invoicing workflows.
Original PR description
**_Steps to reproduce:_** * Install `l10n_br_avatax` and configure Avalara Brazil. * Create at least two customer invoices. * Ensure the fiscal position is set to **Automatic Tax Mapping (Avalara…
**_Steps to reproduce:_** * Install `l10n_br_avatax` and configure Avalara Brazil. * Create at least two customer invoices. * Ensure the fiscal position is set to **Automatic Tax Mapping (Avalara Brazil)**. * Select the invoices and click **Action → Confirm Entries**. **_Observed behavior:_** * A traceback is raised with `ValueError: Expected singleton: account.move(...)` and the invoices cannot be validated. **_Cause:_** * During tax extraction, `_extract_tax_values_from_l10n_br_avatax_detail` accesses `self.invoice_filter_type_domain` while `self` may contain multiple `account.move` records. * Accessing `invoice_filter_type_domain` on a multi-recordset raises an `Expected singleton` error, preventing the validation of multiple invoices. **_Fix:_** * Build the returned tax values by iterating over each invoice in the recordset and using the corresponding `invoice_filter_type_domain`. * This ensures `_extract_tax_values_from_l10n_br_avatax_detail` correctly handles multiple invoices during validation without raising a singleton error. opw-6334761 Forward-Port-Of: odoo/enterprise#126437 Forward-Port-Of: odoo/enterprise#124993
Cancelled Mexican CFDI invoices now keep showing their required fiscal details when reprinted, including QR codes, digital stamps, and fiscal folios. This helps businesses retain legally relevant proof that an invoice was issued and later cancelled.
Original PR description
### Issue before this commit: When an invoice's CFDI cancellation request is confirmed (state moves from sent to cancel), reprinting the invoice PDF no longer displays the fiscal information (QR…
### Issue before this commit: When an invoice's CFDI cancellation request is confirmed (state moves from sent to cancel), reprinting the invoice PDF no longer displays the fiscal information (QR code, digital stamps, fiscal folio/UUID, etc.), even though the signed CFDI attachment is still present on the invoice. ### Steps to reproduce the issue: 1. Download Accounting and l10n_mx 2. Create an invoice and send it to CFDI 3. Select 'Request for cancel' 4. Wait and click retry button in the CFDI tab until the invoice is marked as cancelled 5. Print the invoice again 6. See PDF does not show fiscal information (QR, fiscal folio, etc.) ### Cause of the issue: https://github.com/odoo/enterprise/blob/f6c94d4ca3ef4211a5ab00bf0b39f6a7675c8f79/l10n_mx_edi/models/account_move.py#L904-L909 Once the CFDI is cancelled, the computed field switches to 'cancel', so the condition fails and the method falls back to the generic account.report_invoice_document template, which has no knowledge of CFDI fiscal fields. ### Reason to introduce the fix: A cancelled CFDI invoice is still a legally relevant fiscal document in Mexico and must be reprintable with its fiscal data intact (to prove it was issued and later cancelled). The fix extends the condition to also cover the 'cancel' state, ensuring the CFDI-specific report template is used whenever a valid attachment exists, regardless of whether the CFDI is currently signed or cancelled. opw-6393656 Forward-Port-Of: odoo/enterprise#126466
The aged payable and receivable drill-down now hides invoices and bills that were already fully settled for the selected reporting date. This helps users see only genuinely outstanding items and improves accuracy when reviewing historical balances.
Original PR description
Steps to Reproduce: 1. Create a vendor/customer with multiple bills/invoices. 2. Fully pay one or more, leaving at least one still open for the same partner. 3. Open Accounting > Reporting > Partner…
Steps to Reproduce:
1. Create a vendor/customer with multiple bills/invoices.
2. Fully pay one or more, leaving at least one still open for the same partner.
3. Open Accounting > Reporting > Partner Reports > Aged Payable/Receivable.
4. Set to any date and click into an aging bucket for that partner.
Issue:
The drill-down list shows fully settled bills (residual = 0.00) alongside genuinely outstanding ones. Only surfaces when the partner has at least one open balance — if everything is paid, there is no bucket to click into.
Root Cause:
aged_partner_balance_audit builds the drill-down domain filtering only by reconcile flag, journal type, and date range — never checking residual. Additionally it completely overwrites the XML action domain (account.action_amounts_to_settle) which already had ('amount_residual', '!=', 0), losing that protection entirely.
Fix:
Added ('residual_at_date', '!=', 0) to the domain in aged_partner_balance_audit and set recon_limit in the action context so residual_at_date computes as of the report's 'as of' date rather than today's value:
action['context'] = {
'recon_limit': options['date']['date_to'],
}
Without recon_limit, residual_at_date falls back to amount_residual (today's value) which incorrectly excludes bills that were genuinely open on the report date but paid after it.
Result:
The drill-down now correctly shows only genuinely outstanding items regardless of whether the report is run as of today or a historical date.
opw 6333699
Forward-Port-Of: odoo/enterprise#126021The AI chat now handles screens that do not provide view-switching information, such as Shopfloor, without failing. This prevents users from seeing an error when sending a message after navigating between apps.
Original PR description
### Issue When AI chat is used in views where `config.viewSwitcherEntries` is not initialized, sending a message raises a `TypeError` because the code attempts to call `.map()` on an undefined value.…
### Issue
When AI chat is used in views where `config.viewSwitcherEntries` is not initialized, sending a message raises a `TypeError` because the code attempts to call `.map()` on an undefined value.
### Steps to Reproduce
[Video](https://drive.google.com/file/d/1i7kWDnmv4mebGtf1to12BNHCG5omBTXl/view?usp=sharing)
1. Click the **Ask AI** button.
2. Open the AI chat.
3. Keep it open and navigate to the **Shopfloor** app.
4. Send a message in the AI chat.
### Error
```text
TypeError: Cannot read properties of undefined (reading 'map')
at WithSearch.getCurrentViewInfo
```
### Fix
Safely handle cases where `config.viewSwitcherEntries` is undefined by using optional chaining and falling back to an empty array.
**Before**
```js
result.available_view_types = config.viewSwitcherEntries.map((v) => v.type);
```
**After**
```js
result.available_view_types =
config.viewSwitcherEntries?.map((v) => v.type) || [];
```
opw-6414684
Forward-Port-Of: odoo/enterprise#125821Users can now duplicate several maintenance requests at the same time without the system showing an error. This removes an interruption in maintenance workflows and makes bulk request handling more reliable.
Original PR description
Currently, when a user attempts to duplicate multiple maintenance requests simultaneously, the system throws a ValueError (Expected singleton). This PR fixes that. ### How to reproduce the issue: - Install `mrp_maintenance` module; - Open maintenance request list view; - Select multiple records and try to duplicate them using the Action button; - It will throw a traceback stating a singleton error. ### Expected behavior after PR is merged: Now multiple maintenance requests will be copied without raising any errors. Forward-Port-Of: odoo/enterprise#124255
Updated Peruvian electronic invoice address formatting to match SUNAT's current UBL 2.1 requirements. This helps invoices pass official validation by correctly structuring district and urban subdivision information.
Original PR description
Update electronic invoicing address nodes to align with current SUNAT requirements. This transitions the geographic data formatting from the legacy UBL 2.0 schema to the standard UBL 2.1 specification, ensuring proper structural validation for districts and urban subdivisions. Documentation used: https://cpe.sunat.gob.pe/sites/default/files/inline-files/guia+xml+factura+version+2-1+1+0+(2)_0+(2).pdf opw-6282314 Forward-Port-Of: odoo/enterprise#126380 Forward-Port-Of: odoo/enterprise#121390
The spreadsheet pivot field picker now hides date and datetime fields once all available time breakdowns have already been added. This prevents duplicate entries and makes drag-and-drop behavior more reliable for users configuring pivots.
Original PR description
Current behavior before PR: - Date and datetime fields remained visible even when all their granularities were already added to the pivot. - Users could add the same field with the same granularity multiple times, creating duplicate IDs and causing unexpected drag and drop behavior. Desired behavior after PR is merged: - Hide date and datetime fields from the popup once all available granularities have already been added to the pivot. - This prevents duplicate field IDs and keeps the popup behavior consistent with spreadsheet pivots during drag-and-drop. Task: [6295794](https://www.odoo.com/odoo/project/2328/tasks/6295794) Forward-Port-Of: odoo/enterprise#123280
The Planning app now applies employee and material filter rules correctly when looking at open shifts. This prevents shifts from being incorrectly included or excluded, helping planners see the right staffing and resource information.
Original PR description
Before this commit, the domain wrongly assumes that we always search on shifts having no role or a role containing resources of types 'user' or 'material' (1). Additionally to the basic domain which searches on the shifts having resources of types 'user' or 'material' (2). After this commit, we add a condition on domain (1) to only apply it for open shifts (shifts having no resource_id). no-task Forward-Port-Of: odoo/enterprise#126616 Forward-Port-Of: odoo/enterprise#126247
The Malaysian Statement of Account option now only appears and runs for companies based in Malaysia. This prevents users in other countries from seeing or using a country-specific report that does not apply to them.
Original PR description
### Current behavior: After installing `l10n_my_reports`, the Malaysian's Statement of Account button appears on Aged Receivable for every company, and the partner Action "Print Statement of Account" can be run from non-MY companies ### Expected behavior: To avoid user confusion, it is advised to restrict its visibility so that it is only accessible to Malaysia-specific companies ### Steps to reproduce: 1. Install `l10n_my_reports` 2. Switch to a non-Malaysian company 3. Open Invoicing > Reporting > Aged Receivable 4. Observe the "Statement of Account" button on partner lines ### Cause of the issue: Missing checks for 'MY' company country code in UI and print report action ### Fix: - show the Aged Receivable SoA button only when `company_country_code === 'MY'` - guard `action_print_report_statement_account` for non-MY companies opw-6340854 Forward-Port-Of: odoo/enterprise#126172
Fixed an error where customer Total Due in Point of Sale could show the wrong amount when the company currency differed from the PoS currency. Pay-later balances are now calculated in the correct currency, helping staff see accurate customer debt amounts.
Original PR description
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any…
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any outstanding balance - open the PoS, create an order of USD 100 and validate it with the Customer Account (Pay Later) payment method - open the Customers screen and look at the Total Due of that customer Issue: The Total Due shows about USD 55.56, i.e. the amount converted once too many, instead of the expected USD 100. Cause: get_total_due() sums two amounts that are not expressed in the same currency before converting them. partner.total_due comes from the accounting entries, it is the sum of account.move.line.amount_residual and is therefore in company currency, while total_settled is the sum of pos.payment.amount of the still open sessions, which is in the currency of the order, so the PoS one. The addition is done first and the result is then converted from the company currency to the PoS one, so the pay later payments end up converted a second time. opw-6403320 Forward-Port-Of: odoo/enterprise#126402 Forward-Port-Of: odoo/enterprise#125798
The planning test expectations were updated to match how monthly demand now counts the full current day. This helps ensure manufacturing forecast suggestions correctly include same-day replenishment activity scheduled later in the day.
Original PR description
Updated the forecast suggestion test expectations after monthly demand was updated to count the full current day, so same-day orderpoint replenishment moves scheduled later in the day are also included Community PR: odoo/odoo#262435 TaskID-5490137 Forward-Port-Of: odoo/enterprise#126578 Forward-Port-Of: odoo/enterprise#115944
Appointment booking links now open correctly when the appointment type uses non-ASCII characters, such as Arabic names. This prevents customers from getting stuck in repeated redirects and lets them complete the booking form as expected.
Original PR description
Clicking a slot on an appointment type with a non-ASCII name (for example an Arabic title) puts the browser in an endless 301 loop, so the info form never opens. ### Steps to reproduce - Create an…
Clicking a slot on an appointment type with a non-ASCII name (for example an Arabic title) puts the browser in an endless 301 loop, so the info form never opens. ### Steps to reproduce - Create an appointment type with an Arabic name, e.g. `عنوان`. - Open its page and pick a time slot. - The browser keeps redirecting on `/appointment/<slug>/info` and fails with "too many redirections". ### Cause The info URL is built from the slug `<name>-<id>`, here `عنوان-1`. We build a `URL` with `encodeURIComponent(slug)`, so `url.href` is already encoded once (`عنوان` becomes `%D8%B9...`). But we then navigate with `encodeURI(url.href)`, and `encodeURI` escapes the `%` signs a second time, so `%D8%B9...` becomes `%25D8%25B9...`. The slug is now encoded twice. To canonicalize the URL, the server decodes the request path and the path it rebuilds from the route, once each, and redirects if they differ. For a normal URL they are equal. For ours they are not, because one side is decoded one step less than the other, so the server keeps answering 301 with the same double-encoded URL. An ASCII slug has no `%` for `encodeURI` to escape, so only non-ASCII names hit this. ### Fix Navigate to `url.href` directly. It is already encoded, so the extra `encodeURI` only broke it. Same fix on the manual resource confirmation path. opw-6409641
This update fixes incorrect Italian wording in balance sheet report fields. It improves clarity for Italian-language accounting users and helps reports show the proper labels.
Original PR description
### Steps to reproduce the issue: 1. Download Accounting and l10n_it 2. Install and switch to italian language 3. Go to Balance Sheets and select Balance Sheet (IT) 4. Some words are not correct [Here]( https://docs.google.com/spreadsheets/d/1-w83oAHTxDRIi-W_VSJiscNclw-yijzQUHOgMnTq7jE/edit?gid=0#gid=0) the wrong fields with their correct translations. opw-6424609 Forward-Port-Of: odoo/enterprise#126253
The timesheet assistant now avoids creating suggestions with missing or undefined text. This helps users see clearer, more reliable suggested timesheet entries.
Original PR description
Several aw.rule regexes use (.*) for the capture groups feeding the suggestion name/description, allowing an empty match and producing incorrect suggestions (e.g. "Discussing with undefined") Task-6377168 Forward-Port-Of: odoo/enterprise#125771
Users who open a bank statement line from an in-app notification will now see the related discussion panel. This makes it easier to follow comments and mentions directly from notifications in Accounting.
Original PR description
Problem: When navigating to a bank statement line through a notification, the chatter doesn't appear. Steps to reproduce: 1. Set in app notifications for one of the users 2. Open Accounting > Bank > To Reconcile 3. Select any bank statement line 4. Tag the user from step 1 in a comment 5. Log in as that user 6. Check notifications and click the new notification 7. Notice how the chatter does not appear on the bank statement line after navigating there Cause: The chatter was not enabled on the bank statement line form view. opw-6410186 Forward-Port-Of: odoo/enterprise#125777
This fix makes Belgian payroll export tests for Partena and UCM run against only the company being checked. It prevents demo or additional company data from interfering with test results, improving reliability without changing business functionality.
Original PR description
The UCM and Partena export tests assumed that only the current company was available in the environment. With demo data installed, another allowed company may have a valid external code, so the export wizard does not raise the expected `RedirectWarning`. this commit restricts allowed_company_ids to the company under test to ensure the validation is exercised independently of other installed companies. Related: https://github.com/odoo/enterprise/pull/100932 [error-242729](https://runbot.odoo.com/odoo/error/242729)
This change prevents refund payslips from being recalculated when a user clicks the compute action, preserving their existing payroll lines. Users can still intentionally clear those lines by using the reset action, reducing the risk of accidental payroll changes.
Original PR description
When a payslip is a refund payslip, we don't want to compute it if we click on "compute". The lines can still be reset when clicking on "reset"
User-facing messages and warnings now show selection field values in the user's language instead of leaving some labels untranslated. This improves clarity across accounting, payroll, recruitment, appointments, IoT, point of sale, documents, surveys, and localization reports.
Original PR description
The `selection` attribute of `fields.Selection` is not generally translated (unless it is a function instead of a list). For user facing strings, we generally need to translate the value displayed. Forward-Port-Of: odoo/enterprise#126633 Forward-Port-Of: odoo/enterprise#126538
This update corrects an internal method name used when checking rental dates in the website rental planning flow. It helps ensure the recent rental date validation change is applied consistently, reducing the risk of errors during online rental orders.
Original PR description
In https://github.com/odoo/enterprise/pull/126275, I forgot to rename method `_is_valid_renting_dates` to `_has_valid_rental_dates` opw-6274035
Before this commit: The info, 'You can choose how you want us to send your invoices, and with which electronic format.' was never visible because `invoice_edi_format` is always None. After this commit: Update condition from `invoice_edi_format` to `invoice_edi_formats` to make condition correct and will display info if there are multiple invoice_sending_methods and at-least one edi format. Forward-Port-Of: odoo/odoo#278870
Original PR description
Before this commit: The info, 'You can choose how you want us to send your invoices, and with which electronic format.' was never visible because `invoice_edi_format` is always None. After this commit: Update condition from `invoice_edi_format` to `invoice_edi_formats` to make condition correct and will display info if there are multiple invoice_sending_methods and at-least one edi format. Forward-Port-Of: odoo/odoo#278870
Issue: Every change of the selected order makes the PoS call `pos.config.update_customer_display`, which publishes the order on the bus for the customer display paired with this browser. The device uuid identifying that pairing is only generated when the customer display dialog is opened, so a PoS whose customer display was never opened sends `device_uuid: null` and the server publishes on `UPDATE_CUSTOMER_DISPLAY-null`, a channel nobody can listen to. Steps to reproduce: Open a PoS session
Original PR description
Issue: Every change of the selected order makes the PoS call `pos.config.update_customer_display`, which publishes the order on the bus for the customer display paired with this browser. The device…
Issue: Every change of the selected order makes the PoS call `pos.config.update_customer_display`, which publishes the order on the bus for the customer display paired with this browser. The device uuid identifying that pairing is only generated when the customer display dialog is opened, so a PoS whose customer display was never opened sends `device_uuid: null` and the server publishes on `UPDATE_CUSTOMER_DISPLAY-null`, a channel nobody can listen to. Steps to reproduce: Open a PoS session, never open the customer display, and add a product to an order. Current behaviour: An rpc is sent for each change of the order, and each of them ends up as a bus notification that no customer display can ever receive. Expected behaviour: Nothing is sent as long as no customer display was ever opened. Solution: Skip the rpc while no device uuid exists. A customer display opened in the same browser as the PoS is served by the BroadcastChannel, which is unaffected. task-6408513 Forward-Port-Of: odoo/odoo#277687
This commit fix the regex used in `street_split` to be more complient. Before: address format was "street_name street_number - street_number2" Now, street_number can be in front of street_name. Format is also less strict, allowing multiple numbers in the street_name without skipping the building number. Linked: https://github.com/odoo/enterprise/pull/121674 task-6317758 Forward-Port-Of: odoo/odoo#280081 Forward-Port-Of: odoo/odoo#271855
Original PR description
This commit fix the regex used in `street_split` to be more complient. Before: address format was "street_name street_number - street_number2" Now, street_number can be in front of street_name. Format is also less strict, allowing multiple numbers in the street_name without skipping the building number. Linked: https://github.com/odoo/enterprise/pull/121674 task-6317758 Forward-Port-Of: odoo/odoo#280081 Forward-Port-Of: odoo/odoo#271855
'_getEmptyOrder' could reuse an order whose background sync was still processing; the stale sync response then wiped is_refund and detached the refund line. We now skip orders currently in `syncingOrders` when picking the refund destination so the refund always lands on a clean order and syncs fresh. runbot error : 242604 Forward-Port-Of: odoo/odoo#273703
Original PR description
'_getEmptyOrder' could reuse an order whose background sync was still processing; the stale sync response then wiped is_refund and detached the refund line. We now skip orders currently in `syncingOrders` when picking the refund destination so the refund always lands on a clean order and syncs fresh. runbot error : 242604 Forward-Port-Of: odoo/odoo#273703
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment - Click on the payment method link Traceback: OwlError: The following error occurred in onWillStart: "Cannot find key "pos_payment_provider_cards" in the "view_widgets" registry" Backend views opened from within the PoS UI (order details dialog, drill-down on many2one links, ...) share t
Original PR description
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment…
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment - Click on the payment method link Traceback: OwlError: The following error occurred in onWillStart: "Cannot find key "pos_payment_provider_cards" in the "view_widgets" registry" Backend views opened from within the PoS UI (order details dialog, drill-down on many2one links, ...) share their arch with the backend, but `point_of_sale._assets_pos` excludes everything under `static/src/backend/`, so widgets defined there (e.g. `pos_payment_provider_cards`, `lna_checklist`, `point_of_sale_test_epos`) are never registered in the PoS UI. Unlike missing field widgets, which fall back to the default widget with a warning, an unknown `<widget>` node makes the whole view crash since `Widget.parseWidgetNode` reads the registry without a fallback. Those widgets are backend configuration helpers that are irrelevant in a PoS session, so instead of bundling each of them (and any future one) in the PoS assets, patch `Widget.parseWidgetNode` in the PoS bundle to skip unknown widgets with a warning, like missing field widgets do. This covers the form, list and kanban arch parsers at once. opw-6382156 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279823 Forward-Port-Of: odoo/odoo#276912
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ##
Original PR description
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ### Cause of the issue: Issue comes from this commit 9396790e9cc1ce1c6e5c29b71b5629b31fb16458 where it has been forgotten to disable the translation. ### Reason to introduce the fix: Meet the requirements of the electronic invoice. opw-6023971 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273042
Use "VAT" instead of "TAX" for the default UK tax groups. Also set "Subtotal" as their preceding subtotal label so that it replaces "Untaxed Amount". task-[6413495](https://www.odoo.com/odoo/project/967/tasks/6413495) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280144 Forward-Port-Of: odoo/odoo#278351
Original PR description
Use "VAT" instead of "TAX" for the default UK tax groups. Also set "Subtotal" as their preceding subtotal label so that it replaces "Untaxed Amount". task-[6413495](https://www.odoo.com/odoo/project/967/tasks/6413495) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280144 Forward-Port-Of: odoo/odoo#278351
Description of the issue/feature this PR addresses: Mail server ports are identifiers rather than quantities. The incoming and outgoing mail server views use the unsupported `format` option, so locale-based integer formatting remains enabled. Steps to reproduce: 1. Enable developer mode. 2. Go to Settings > Technical > Email > Outgoing Mail Servers. 3. Create a server and set SMTP Port to `8069`. 4. Move focus away from the field. 5. The same issue occurs on an Incomin
Original PR description
Description of the issue/feature this PR addresses: Mail server ports are identifiers rather than quantities. The incoming and outgoing mail server views use the unsupported `format` option, so…
Description of the issue/feature this PR addresses: Mail server ports are identifiers rather than quantities. The incoming and outgoing mail server views use the unsupported `format` option, so locale-based integer formatting remains enabled. Steps to reproduce: 1. Enable developer mode. 2. Go to Settings > Technical > Email > Outgoing Mail Servers. 3. Create a server and set SMTP Port to `8069`. 4. Move focus away from the field. 5. The same issue occurs on an Incoming Mail Server with a port such as `10143`. Current behavior before PR: Ports are displayed with thousands separators, e.g. `8,069` and `10,143`. Desired behavior after PR is merged: Mail server ports remain unformatted, e.g. `8069` and `10143`. Fixes #275937 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr "As a recent Computer Engineering graduate, I made my first open-source contribution to Odoo." :) Forward-Port-Of: odoo/odoo#278329
The test for `hr_leave_attendance_report` failed Runbot's faketime tests for two reasons: * The report's view use SQL's reserved syntax `CURRENT_DATE` which always resolves to real system clock, and ignores Odoo's faketime mechanism. * The three tests used hardcoded dates. Since the report is exclusively concerned with the window of last 13 months. Faking the time in a future date further than this led to wrong results. This commit fixes both issues by: 1. Using `now()::date`
Original PR description
The test for `hr_leave_attendance_report` failed Runbot's faketime tests for two reasons: * The report's view use SQL's reserved syntax `CURRENT_DATE` which always resolves to real system clock, and ignores Odoo's faketime mechanism. * The three tests used hardcoded dates. Since the report is exclusively concerned with the window of last 13 months. Faking the time in a future date further than this led to wrong results. This commit fixes both issues by: 1. Using `now()::date` in the view instead of `CURRENT_DATE`. 2. Replacing the hardcoded dates in the tests by dates computed relative to `fields.Date.today()`. Runbot Errors: [1](https://runbot.odoo.com/odoo/runbot.build.error/944585), [2](https://runbot.odoo.com/odoo/runbot.build.error/944585/runbot.build.error/runbot.build.error/944584) Forward-Port-Of: odoo/odoo#280380 Forward-Port-Of: odoo/odoo#279337
PoS loads product categories from both the PoS configuration and the preparation printers. Before this commit, if a child category was included in the PoS configuration, but its parent was only included in a preparation printer, the parent category was loaded in the frontend without being visible. As a result, the child category was also hidden, even though its products were still available. How to reproduce: - Create a parent category. - Create a child category containing a product. -
Original PR description
PoS loads product categories from both the PoS configuration and the preparation printers. Before this commit, if a child category was included in the PoS configuration, but its parent was only included in a preparation printer, the parent category was loaded in the frontend without being visible. As a result, the child category was also hidden, even though its products were still available. How to reproduce: - Create a parent category. - Create a child category containing a product. - Limit the PoS categories to the child category. - Create a preparation printer and assign the parent category to it. - Open the PoS. - The products are available, but the child category is not visible. opw-6381119 Forward-Port-Of: odoo/odoo#279459 Forward-Port-Of: odoo/odoo#276782
Before this commit, the chat window test "mark as read when opening chat window" failed at random on runbot, on the store fetches checked at teardown: 14. [step] unverified steps > Steps: [ "store fetch: /discuss/channel/messages", ] This happens because waitStoreFetch resolves as soon as the mock server serves the request, so the thread can still be loading when the test posts bob's message. As a result the scroll to unread, which only the loaded thread applies, is st
Original PR description
Before this commit, the chat window test "mark as read when opening chat window" failed at random on runbot, on the store fetches checked at teardown:
14. [step] unverified steps
> Steps: [
"store fetch: /discuss/channel/messages",
]
This happens because waitStoreFetch resolves as soon as the mock server serves the request, so the thread can still be loading when the test posts bob's message. As a result the scroll to unread, which only the loaded thread applies, is still pending when the chat window closes, and re-opening it loads around the new message separator: that second fetch is the one no assertion verifies.
This commit waits for the loaded thread before posting the message.
https://runbot.odoo.com/odoo/error/242447
Forward-Port-Of: odoo/odoo#280359Before this commit, test_01_invite_by_email_flow could fail right after a tour that succeeded, on a loaded runbot: ``` AssertionError: res.partner(2417,) not found in res.partner(2416,) ``` This happens because the tour ends on the click on "Invite to Group Chat", which only starts the add_members and invite_by_email calls. The test closes the browser and reads the channel members right after, so under load the calls never reach the server. Note that the tour did wait for the invite p
Original PR description
Before this commit, test_01_invite_by_email_flow could fail right after a tour that succeeded, on a loaded runbot: ``` AssertionError: res.partner(2417,) not found in res.partner(2416,) ``` This happens because the tour ends on the click on "Invite to Group Chat", which only starts the add_members and invite_by_email calls. The test closes the browser and reads the channel members right after, so under load the calls never reach the server. Note that the tour did wait for the invite panel to close, until that panel became a dialog: the step waited for any panel to be gone, and the member list stays open. This commit waits for the invited member in the member list and for the dialog to close, which only happens once both calls are done. https://runbot.odoo.com/odoo/error/944291 Forward-Port-Of: odoo/odoo#280356
Followup of odoo/odoo@41fe2ebdb9cc. Before this commit, when trying to submit a track proposal with a speaker image, the request failed with: ``` TypeError: event.track.image: use BinaryValue instead of bytes ``` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Followup of odoo/odoo@41fe2ebdb9cc. Before this commit, when trying to submit a track proposal with a speaker image, the request failed with: ``` TypeError: event.track.image: use BinaryValue instead of bytes ``` --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Normalize client IPv6 addresses to their /64 network prefix when generating device keys. This prevents the same IPv6 user from being tracked as multiple devices due to changing interface identifiers while preserving IPv4 behavior. This reduces the number of devices in the session while maintaining reliability. The original IP address will be used to determine device location. Task-6397512 Forward-Port-Of: odoo/odoo#277117
Original PR description
Normalize client IPv6 addresses to their /64 network prefix when generating device keys. This prevents the same IPv6 user from being tracked as multiple devices due to changing interface identifiers while preserving IPv4 behavior. This reduces the number of devices in the session while maintaining reliability. The original IP address will be used to determine device location. Task-6397512 Forward-Port-Of: odoo/odoo#277117
A user with own sales permissions won't be able to change the task partner when that task has a timesheet configured. Description of the issue/feature this PR addresses: - With a user with bare sales permissions (own sales) go to a task with timesheets and a sale order linked to it - Try to change the Customer for the task and save Current behavior before PR: <img width="1148" height="308" alt="image" src="https://github.com/user-attachments/assets/f0ccd25c-757b-455f-be36-68599de18c
Original PR description
A user with own sales permissions won't be able to change the task partner when that task has a timesheet configured. Description of the issue/feature this PR addresses: - With a user with bare sales permissions (own sales) go to a task with timesheets and a sale order linked to it - Try to change the Customer for the task and save Current behavior before PR: <img width="1148" height="308" alt="image" src="https://github.com/user-attachments/assets/f0ccd25c-757b-455f-be36-68599de18cd3" /> Desired behavior after PR is merged: No access error cc @moduon MT-15215 OPW-6364376 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273916
During the FWP, the inherit has been mistakingly inverted. PINT_EU should inherit PINT and EN16931 as dictated in the pint documentation. no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280321
Original PR description
During the FWP, the inherit has been mistakingly inverted. PINT_EU should inherit PINT and EN16931 as dictated in the pint documentation. no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280321
Currently, a transfer is marked as 'Printed' only when the 'Picking Operations' report is printed using the Print button in the 'ready' state. If the same report is printed from the actions (gear) menu, the transfer is not marked as printed. This PR ensures that printing the 'Picking Operations' report from the actions menu also marks the transfer as 'Printed'. **Steps to reproduce:** - Install the stock module. - Open the Transfers list view. - Add custom group for 'Printed'. - Open a
Original PR description
Currently, a transfer is marked as 'Printed' only when the 'Picking Operations' report is printed using the Print button in the 'ready' state. If the same report is printed from the actions (gear)…
Currently, a transfer is marked as 'Printed' only when the 'Picking Operations' report is printed using the Print button in the 'ready' state. If the same report is printed from the actions (gear) menu, the transfer is not marked as printed. This PR ensures that printing the 'Picking Operations' report from the actions menu also marks the transfer as 'Printed'. **Steps to reproduce:** - Install the stock module. - Open the Transfers list view. - Add custom group for 'Printed'. - Open a transfer in the 'ready' state and print the 'Picking Operations' report using the Print button. Notice that the transfer is marked as 'Printed'. - Open another transfer in the 'ready' state and print the 'Picking Operations' report from the actions menu. - Observe that the transfer is not marked as Printed. The same issue occurs when printing it from list view. **Expected behavior:** A transfer in the 'ready' state should be marked as Printed whenever the 'Picking Operations' report is printed, regardless of whether it is triggered from the 'Print' button or the actions menu. close #235129 Forward-Port-Of: odoo/odoo#276582
Repro steps: 1) Create an invoice 2) Activate auto post (monthly for example) 3) Confirm the invoice, a new draft invoice will be created 4) Reset to draft 5) Confirm again Problem: A second draft would be created, and next period, 2 invoices would be confirmed Fix: This commit deletes the next auto post recurrence of an invoice, if that next recurrence is in draft, and the invoice is being set to draft. It also prevents creating a recurrence at a date if there is already an exi
Original PR description
Repro steps: 1) Create an invoice 2) Activate auto post (monthly for example) 3) Confirm the invoice, a new draft invoice will be created 4) Reset to draft 5) Confirm again Problem: A second draft would be created, and next period, 2 invoices would be confirmed Fix: This commit deletes the next auto post recurrence of an invoice, if that next recurrence is in draft, and the invoice is being set to draft. It also prevents creating a recurrence at a date if there is already an existing recurrent move on that date. task-6311219 Forward-Port-Of: odoo/odoo#279159
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#279784 Forward-Port-Of: odoo/odoo#271364
Original PR description
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#279784 Forward-Port-Of: odoo/odoo#271364
*:mrp_subcontracting_purchase Issue before this commit: ======================== - In inter-warehouse transfers with `multi-step delivery` and in multi-step manufacturing flows, demand moves were not correctly counted in the monthly demand. - Also, direct transfers to customer and subcontracting locations generated from `orderpoint` were also not counted correctly (when checked before move scheduled on the same day). This resulted in lower monthly demand values than the actual demand and
Original PR description
*:mrp_subcontracting_purchase Issue before this commit: ======================== - In inter-warehouse transfers with `multi-step delivery` and in multi-step manufacturing flows, demand moves were not…
*:mrp_subcontracting_purchase Issue before this commit: ======================== - In inter-warehouse transfers with `multi-step delivery` and in multi-step manufacturing flows, demand moves were not correctly counted in the monthly demand. - Also, direct transfers to customer and subcontracting locations generated from `orderpoint` were also not counted correctly (when checked before move scheduled on the same day). This resulted in lower monthly demand values than the actual demand and could lead to inaccurate purchase planning. Steps to Reproduce: ========================= - Install `purchase_stock` module and enable multi-step routes. - Set the Outgoing Shipments in the warehouse to 2-step/3-step. - Create a second warehouse and configure it to `resupply from another warehouse`. - Create a storable product and assign a vendor. - Create an orderpoint for the product in the second warehouse, set the route to the warehouse resupply route, and trigger the replenishment. - Go to Purchase → Create RFQ for the vendor and open the catalog. Observation: The replenishment transfer demand is not correctly counted in the monthly demand Cause of the issue: ========================= - In [PR](https://github.com/odoo/odoo/pull/244180), the monthly demand move domain was updated to filter out intermediate customer delivery moves using `move_dest_ids.origin_returned_move_id`. However, inter-warehouse replenishment delivery moves also have `move_dest_ids` linked to receipt moves of the other warehouse, but `origin_returned_move_id is not set` since they are not return move Because of this, these valid demand moves were incorrectly excluded from the monthly demand computation. - Also, in inter-warehouse flows with multi-step delivery, `delivery moves` stay in the `waiting state` since they wait for another operation, so they were also not counted. Additionally, `orderpoint-triggered` moves use a `fixed midday scheduled time`, and since monthly demand was computed using the current timestamp as the limit date, same-day moves could be excluded if checked before midday. After This Commit: ========================= - The monthly demand move domain was updated to correctly count inter-warehouse, manufacturing, and subcontracting resupply demand moves while still avoiding inflated demand from intermediate moves. The move state domain was also updated to `include waiting moves` in multi-step flows, and the limit date now uses the full current day so same day moves are counted correctly. Enterprise PR: odoo/enterprise#115944 TaskID-5490137 Forward-Port-Of: odoo/odoo#280167 Forward-Port-Of: odoo/odoo#262435
When you refuse an applicant, and there is a survey user_input linked, you are not able to do it because applicant officers don't have access 'write' on the model. So we do it in sudo. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
When you refuse an applicant, and there is a survey user_input linked, you are not able to do it because applicant officers don't have access 'write' on the model. So we do it in sudo. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
## Problem `pttExtensionHookService` registers a global `window.addEventListener("message", ...)` handler that reads `data.from` without checking that `data` is defined first: ```js browser.addEventListener("message", ({ data, origin, source }) => { const rtc = env.services["discuss.rtc"]; if ( source !== window || origin !== location.origin || data.from !== "discuss-push-to-talk" || // <- crashes if data is undefined (!rtc && data.type !== "answer-is-
Original PR description
## Problem `pttExtensionHookService` registers a global `window.addEventListener("message", ...)` handler that reads `data.from` without checking that `data` is defined first: ```js…
## Problem
`pttExtensionHookService` registers a global `window.addEventListener("message", ...)`
handler that reads `data.from` without checking that `data` is defined first:
```js
browser.addEventListener("message", ({ data, origin, source }) => {
const rtc = env.services["discuss.rtc"];
if (
source !== window ||
origin !== location.origin ||
data.from !== "discuss-push-to-talk" || // <- crashes if data is undefined
(!rtc && data.type !== "answer-is-enabled")
) {
return;
}
...
```
Any same-window, same-origin `postMessage` sent by an unrelated browser
extension (a common content-script <-> injected-script pattern) can carry
`data === undefined`. The `source !== window` and `origin !== location.origin`
checks only filter out cross-window/cross-origin messages, so a same-origin
message from any other extension reaches this handler and crashes with:
```
TypeError: Cannot read properties of undefined (reading 'from')
```
This surfaces as an uncaught client error on any page with Discuss loaded,
after some time, unrelated to what the user is doing. The Discuss
push-to-talk extension itself does not need to be installed to trigger it,
since the crash happens before checking whether the message actually
originated from that extension.
## Solution
Use optional chaining (`data?.from`) so unrelated same-origin messages with
no `data` are safely ignored instead of crashing.
## Verification
- Reproduced against the live production `web.assets_web.min.js` bundle
(traceback matches exactly).
- Confirmed the bug is still present in the latest `18.0` of both `OCA/OCB`
and `odoo/odoo` (no newer commit touches this file since
`dc58ef1ad904`, which fixes an unrelated issue).
Forward-Port-Of: odoo/odoo#280079
Forward-Port-Of: odoo/odoo#279476By default event notifications are configured with positive integers to state how many minutes/hours/days they should be triggered before an event starts. This works fine in within Odoo. But in an ICS file a TRIGGER with such positive integer means it starts after the event. For example ICS file generated by Odoo contains TRIGGER;related=START:PT15M but it should be negative: TRIGGER;related=START:-PT15M (note the minus) in order to trigger before the event. See [here](https://icalendar.org/iCal
Original PR description
By default event notifications are configured with positive integers to state how many minutes/hours/days they should be triggered before an event starts. This works fine in within Odoo. But in an ICS file a TRIGGER with such positive integer means it starts after the event. For example ICS file generated by Odoo contains TRIGGER;related=START:PT15M but it should be negative: TRIGGER;related=START:-PT15M (note the minus) in order to trigger before the event. See [here](https://icalendar.org/iCalendar-RFC-5545/3-8-6-3-trigger.html) for reference. Current behavior before PR: The reminder is triggered AFTER the event start Desired behavior after PR is merged: The reminder is triggered BEFORE the event start Closes #245052. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274744
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
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
Problem: The `product_label_section_and_note_field` widget ignores the `no_open` option in list views. The `m2oProps` getter overrides the framework's native `p.canOpen` property, hardcoding the clickable state based purely on readonly status. Purpose: Ensure the widget respects standard framework options by the `p.canOpen` with the business logic, restoring the ability to disable record navigation. Steps to Reproduce on Runbot: - Go to Purchase app and open a quotation. - Open Odoo St
Original PR description
Problem: The `product_label_section_and_note_field` widget ignores the `no_open` option in list views. The `m2oProps` getter overrides the framework's native `p.canOpen` property, hardcoding the clickable state based purely on readonly status. Purpose: Ensure the widget respects standard framework options by the `p.canOpen` with the business logic, restoring the ability to disable record navigation. Steps to Reproduce on Runbot: - Go to Purchase app and open a quotation. - Open Odoo Studio. - Click on the product table and select "Edit list view". - Click on the product column. - On the sidebar, go to properties and activate "Disable opening". - Close Studio and click the product name on a line. - The form view action is triggered. opw-6422065 Forward-Port-Of: odoo/odoo#279221
Previously, we did not prevent FRCTC from registering through Peppol, even though FRCTC is not supported in Peppol. French companies could attempt to register in Peppol with FRCTC, which caused many errors. task-6421930 Forward-Port-Of: odoo/odoo#278782
Original PR description
Previously, we did not prevent FRCTC from registering through Peppol, even though FRCTC is not supported in Peppol. French companies could attempt to register in Peppol with FRCTC, which caused many errors. task-6421930 Forward-Port-Of: odoo/odoo#278782
Before this commit, this test was failing non-deterministically on on some machines: ``` show banner for new message after thread was read from another device ``` With the following error: ``` Error: Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))" (Timeout of 3 seconds). Found 0 instead. ``` This happens because while the message list has 20 messages, each message is 1-line long. That means on many monitors the bottom of conversation is visible and thus it c
Original PR description
Before this commit, this test was failing non-deterministically on on some machines:
```
show banner for new message after thread was read from another device
```
With the following error:
```
Error: Failed to find 1 of ".o-mail-Thread-banner:has(:text('1 new message'))" (Timeout of 3 seconds). Found 0 instead.
```
This happens because while the message list has 20 messages, each message is 1-line long. That means on many monitors the bottom of conversation is visible and thus it can mark as read automatically the conversation. When this happens the banner is removed, thus the last step would fail.
This commit fixes the issue by making each message body bigger, so that this is very unlikely to see the bottom of message list, therefore avoiding the auto-mark as read from reaching the bottom of conversation.
Forward-Port-Of: odoo/odoo#280103When running `ŧest_free_reservation`, it could happen on very rare occasions that both moves would be created at a different second. In such cases, the test would fail. Since we want to test the case with *exact* same dates, we can't use `assertAlmostEqual` which is usually better for dates. Instead, we freeze the time for the duration of the creation / assignation. runbot-944453 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of:
Original PR description
When running `ŧest_free_reservation`, it could happen on very rare occasions that both moves would be created at a different second. In such cases, the test would fail. Since we want to test the case with *exact* same dates, we can't use `assertAlmostEqual` which is usually better for dates. Instead, we freeze the time for the duration of the creation / assignation. runbot-944453 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279954 Forward-Port-Of: odoo/odoo#278103
Ensure combo prices are computed in the backend. Forward-Port-Of: odoo/odoo#279919 Forward-Port-Of: odoo/odoo#279652
Original PR description
Ensure combo prices are computed in the backend. Forward-Port-Of: odoo/odoo#279919 Forward-Port-Of: odoo/odoo#279652
If the badge selection widget value is false, you get an error as it cannot includes in false. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
If the badge selection widget value is false, you get an error as it cannot includes in false. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Before this commit, turning the camera on during a call could leave the camera off in every member's UI, including the local user's own tile, while the video was already being sent. This happens because toggleVideo awaits network.updateUpload before updateAndBroadcast, and updateUpload waits on the ready promise of every peer. A single member whose handshake never completes holds isCameraOn and isScreenSharingOn for everyone. This commit fixes the issue by broadcasting the state first and
Original PR description
Before this commit, turning the camera on during a call could leave the camera off in every member's UI, including the local user's own tile, while the video was already being sent. This happens because toggleVideo awaits network.updateUpload before updateAndBroadcast, and updateUpload waits on the ready promise of every peer. A single member whose handshake never completes holds isCameraOn and isScreenSharingOn for everyone. This commit fixes the issue by broadcasting the state first and awaiting the upload after. Note that updateUpload sends its info snapshot to the peers synchronously, so they still learn the new track. Back-port of https://github.com/odoo/odoo/pull/279106 Forward-Port-Of: odoo/odoo#280492 Forward-Port-Of: odoo/odoo#280014
The tracking field was removed from point_of_sale in https://github.com/odoo/odoo/pull/241368 However, forward ports may still keep the field in fixes prior to 19.3 like here in https://github.com/odoo/odoo/pull/279952 This breaks silently because issues only occur when stock is not installed so the forward-port build won't fail but some nightly builds will. runbot-error-944823
Original PR description
The tracking field was removed from point_of_sale in https://github.com/odoo/odoo/pull/241368 However, forward ports may still keep the field in fixes prior to 19.3 like here in https://github.com/odoo/odoo/pull/279952 This breaks silently because issues only occur when stock is not installed so the forward-port build won't fail but some nightly builds will. runbot-error-944823
[FIX] html_builder: prevent crash on legacy image shapes When the Website Editor encounters an image shape that does not exist in the registry, it fatally crashes upon saving (`TypeError: Cannot read properties of undefined`), blocking the user from saving the page. While an upgrade script exists to remap these shapes ([commit https://github.com/odoo/odoo/commit/f348be018f5740a31754494c905ea2b61bb718be](https://github.com/odoo/upgrade/commit/f348be0dcbc63c1f74f742b562509f81767564c0)), ti
Original PR description
[FIX] html_builder: prevent crash on legacy image shapes When the Website Editor encounters an image shape that does not exist in the registry, it fatally crashes upon saving (`TypeError: Cannot read…
[FIX] html_builder: prevent crash on legacy image shapes When the Website Editor encounters an image shape that does not exist in the registry, it fatally crashes upon saving (`TypeError: Cannot read properties of undefined`), blocking the user from saving the page. While an upgrade script exists to remap these shapes ([commit https://github.com/odoo/odoo/commit/f348be018f5740a31754494c905ea2b61bb718be](https://github.com/odoo/upgrade/commit/f348be0dcbc63c1f74f742b562509f81767564c0)), timeline gaps leave SaaS databases vulnerable. For example, if a client upgraded their database to 17.0 in Feb 2024, they bypassed the migration script merged in Dec 2024. This leaves the legacy shape permanently orphaned inside their modern views. This commit adds a `getImageShape` fallback. Instead of crashing,the editor now defaults to standard values and renders "None" in the UI, allowing the user to select a new shape and save their work. Steps to Reproduce: 1. Install Website. 2. Go to Site -> HTML / CSS Editor. 3. Add `data-shape="web_editor/basic/bsc_organic_2"` to an <img> tag. 4. Click "Edit" to open the Website Builder. 5. Click the image, OR click "Save". 6. JS traceback. [opw-6286044](https://www.odoo.com/odoo/my-support-tasks/6286044?debug=assets) [opw-6291591](https://www.odoo.com/odoo/my-support-tasks/6291591?debug=assets) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278686 Forward-Port-Of: odoo/odoo#270356
The `selection` attribute of `fields.Selection` is not generally translated (unless it is a function instead of a list). For user facing strings, we generally need to translate the value displayed. 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#280257 Forward-Port-Of: odoo/odoo#280094
Original PR description
The `selection` attribute of `fields.Selection` is not generally translated (unless it is a function instead of a list). For user facing strings, we generally need to translate the value displayed. 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#280257 Forward-Port-Of: odoo/odoo#280094