Thursday, September 3, 2026
37 changes · saas-19.2
Resolved issues and error corrections
Uploading BIS3 vendor bill XML files no longer fails when the supplier country is missing from the file. Odoo now checks for the missing country and falls back to the country set on the related partner record, helping Belgian accounting users process vendor bills more reliably.
Original PR description
Steps to reproduce: - Install accounting and create BE company - Create BIS3 xml where there's no country for AccountingSupplierParty - From BE company, upload the xml vendor bill Current behavior: Error when trying to upload xml Expected behavior: No error Cause of issue: Currently there's no check to see if a country exists in the BIS3 xml. This PR adds a check and adds a fallback to get the country attached to the partner record if there's none present in the xml opw-6498830 Forward-Port-Of: odoo/odoo#284862 Forward-Port-Of: odoo/odoo#284554
Financial reports no longer show the unallocated earnings or losses row when it has a zero balance across all report columns. This keeps trial balance and related reports cleaner by removing rows that do not add useful information.
Original PR description
… zero The unallocated earnings/losses line was displayed even when its balance was zero in every column group, cluttering the report with uninformative rows. We therefore filter out lines whose balance is zero across all column groups. Forward-Port-Of: odoo/enterprise#129597 Forward-Port-Of: odoo/enterprise#129129
This fixes an installation issue where the Restaurant point of sale module could fail if the main Point of Sale module had not been upgraded first. The change uses a more stable receipt section so upgrades and customizations are less likely to break.
Original PR description
The template for the preparation tickets was using an xpath targeting a newly added div element. This raised an error when installing the `pos_restaurant` module while an old version of `point_of_sale` was still in place, since the customer would need to manually upgrade `point_of_sale` first to have that new div element available. We now use receipt-header as the xpath target, which was always present in the template. We also refill `pos_self_order.pos_order_change_receipt` to prevent breaks with custo. --- Report: https://github.com/odoo/odoo/pull/267161#discussion_r3758115362
Signed quotation documents are now saved as automated communication entries, so customers can still see them but cannot delete the attached signed PDF from the portal. This prevents the loss of the only signed quotation record while payment is still pending, without changing normal customer comments.
Original PR description
Issue: A customer who signs a quotation can delete the chatter entry containing the generated signed PDF. For quotations awaiting a wire transfer, this can remove the only retrievable snapshot of the…
Issue: A customer who signs a quotation can delete the chatter entry containing the generated signed PDF. For quotations awaiting a wire transfer, this can remove the only retrievable snapshot of the signed quotation before the order is confirmed. Steps to reproduce: - Create a quotation requiring an online signature and payment. - Sign it from the customer portal and select wire transfer. - Delete the "Order signed by ..." entry from the portal communication history. Cause: The signing endpoint posts the generated PDF as a regular customer authored comment. Portal chatter allows customers to update their own comments, and deleting one clears its attachments, so the signed PDF is physically removed. https://github.com/odoo/odoo/blob/e479111294b11058038defc31505cc81ac1f1821/addons/sale/controllers/portal.py#L348-L358 Solution: Classify the signed document entry as an automated comment. This keeps it visible and attributed to the customer while ensuring that both the portal interface and backend message rules treat its content and attachment as immutable. Regular customer comments keep their existing behavior. opw-6466029 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Appointments calendar now opens on the next upcoming booking instead of jumping to the furthest future booking. This makes it faster for staff to review current schedules and avoids confusion when managing appointment types with bookings across multiple dates.
Original PR description
Problem: The bookings calendar of an appointment type opens on the week of the most distant booking instead of the next one, even when a booking exists later the same day. Cause:…
Problem: The bookings calendar of an appointment type opens on the week of the most distant booking instead of the next one, even when a booking exists later the same day. Cause: `action_calendar_meetings` sets the landing date from `appointments[0].start`, where `appointments` is `self.meeting_ids.filtered_domain(domain)`. `calendar.event` is ordered on `start desc` and a one2many is read in the order of its comodel, so the first record is the furthest booking rather than the next one. The original `search([...], order='start')` was replaced by the one2many in 14b5caccc325 (odoo/enterprise#23191). Solution: Sort the filtered bookings on `start` in `action_calendar_meetings`. That method is the only place the initial date is built, and `action_calendar_event_view_request` reuses it for the gantt start date, so both entry points are covered. `calendar.event` keeps its `start desc` order, which the booking list views rely on. Steps to reproduce: - Go to Appointments. - Open the appointment type "Schedule a Demo" and click Appointments. - Click New, set the date to later today, save and go back. - Click New, set the date to one year from now, save and go back. - Go back to Appointments, reopen "Schedule a Demo" and click Appointments. - Switch to the calendar view. - Observe that the calendar opens on the week of the booking one year from now. Ticket [link](https://www.odoo.com/odoo/project.task/6480029) opw-6480029 Forward-Port-Of: odoo/enterprise#129000
French VAT closing entries now correctly include VAT credit carried over from the previous period. This ensures tax return journal entries remain compliant with French accounting requirements and accurately reflect prior-period credits.
Original PR description
### Issue before this commit: When generating a tax closing entry for France, the VAT credit carryover from the previous period is missing from the journal entry lines. ### Steps to reproduce the…
### Issue before this commit: When generating a tax closing entry for France, the VAT credit carryover from the previous period is missing from the journal entry lines. ### Steps to reproduce the issue: 1. Download Accounting and l10n_fr 2. Go to Vendor > Bills 3. Create a vendor bill with date in June and price > 0 (ex. 1000$) and the 20% G tax that produce a 200$ VAT tax 4. Go to Customers > Invoices 5. Create an invoice with price > 0 (ex. 9000$), the date in July and the 20% G tax that will produce a 1800$ VAT tax 6. Go to Tax Return and validate all opened months up to July and see that for June the balance is -200$ 9. Then go to View Entries of July using the 3 dots next to the "submit" button and see that there is no mentioning of the 200$ carry over of credit from the month before ### Cause of the issue: The issue stems from a structural change in the core code where the logic to evaluate and balance the tax receivable account was removed from the _add_tax_group_closing_items method. Consequently, the VAT closing entry now only processes the current period's taxes and there is no reporting of any carried-forward VAT credits. ### Reason to introduce the fix: French accounting rules strictly require the carried-forward VAT credit to be explicitly integrated into the current period's tax closing entry. opw-6438648
The Helpdesk SLA report now calculates “Hours Open” from ticket creation until the ticket is closed, matching the main ticket analysis report. This gives managers a more accurate view of how long support tickets remain open and avoids confusing it with assignment-time metrics.
Original PR description
1. Open Helpdesk > Tickets and create a ticket on the team "Customer Care", assigned to yourself 2. More than an hour later, move it to the "Solved" stage to close it 3. Open Helpdesk > Reporting > Ticket Analysis, switch to the pivot view and pick the "Hours Open" measure -> the ticket holds the hour it stayed open 4. Open Helpdesk > Reporting > SLA Status Analysis and pick the "Hours Open" measure as well -> the ticket holds nothing, as it was assigned as soon as it was created odoo/enterprise#47454 added the "Hours Open" measure of the ticket analysis to the SLA status analysis, but computes it up to the assignment date instead of the closing date. The measure therefore holds the hours until the ticket was assigned, which the report already offers as "Working Hours to Assign". With this commit, both reports count the hours from the creation of the ticket to its closing. Forward-Port-Of: odoo/enterprise#130170
This fix makes a Canadian payment validation test use a consistent item order, preventing false failures in automated checks. It helps keep release validation reliable without changing customer-facing payment behavior.
Original PR description
Sorts the expected items in `test_cpa005` to ensure consistent ordering. runbot error: https://runbot.odoo.com/odoo/error/941567 Forward-Port-Of: odoo/enterprise#127703
This fix makes the mail reply area behave consistently when users press Escape, even if mention suggestions are still loading or the screen updates. It prevents the suggestion list from unexpectedly reopening and blocking the intended action, reducing flaky behavior in discussions.
Original PR description
Two independent causes made "reply: discard on pressing escape" red, one commit each. "[FIX] mail: wait for the mention suggestions before Escape" is the one that fixes the reported failure, and it holds on every branch: the test presses Escape while the mention fetch is in flight, and the suggestions arriving from the server re-open the list that Escape closed, so the re-opened list takes the second Escape and the reply is never discarded. The test now waits for the fetched suggestions before pressing Escape. "[FIX] mail: keep the suggestion list closed on a re-render" backports "[FIX] mail: keep composer suggestion list closed on unrelated re-render", which entered at 19.0 and never came down. Here NavigableList is re-opened on every patch, so opening the emoji picker after Escape brings the dismissed list back, and it then steals the Escape meant for the picker. https://runbot.odoo.com/odoo/error/946314 Forward-Port-Of: odoo/odoo#286041 Forward-Port-Of: odoo/odoo#284725
This fix ensures analytic plan applicability rules do not incorrectly override the default setting on screens without a specific business context, such as Work Centers or Employee records. Users will now see the expected analytic distribution requirement, reducing confusion and preventing unnecessary mandatory analytic entries.
Original PR description
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or…
### Issue: When an analytic plan has applicability lines with a company filter, the applicability is incorrectly applied on views that do not define a `business_domain`, such as Work Centers or Employee views For example, if a plan has: - Default Applicability: Unavailable - A line with Domain: Invoice, Company: My Company, Applicability: Mandatory Opening the analytic distribution on a Work Center shows `Mandatory` instead of the default `Unavailable` ### Cause: In commit https://github.com/odoo/odoo/commit/ffcf2ee1a3185ef73db93bfd95625844506692c5 `_get_score` was updated to return `0.5` when the applicability line's company matches the caller's company, even when no `business_domain` is provided In `_get_applicability`, the loop selects the first rule whose score exceeds the current minimum, which starts at `0`: https://github.com/odoo/odoo/blob/710e056e5171af2ab72d7d7793da3518f12faf5e/addons/analytic/models/analytic_plan.py#L255-L264 A score of `0.5` is enough to win over the default applicability, so a company-only match on a domain-specific rule incorrectly overrides the default when no `business_domain` is passed ### Steps to reproduce: - Install `mrp` and `accountant` with demo data - Enable Analytic Accounting in Settings - Open the Internal analytic plan and edit its applicability line: -- Remove the account prefix -- Default Applicability: Unavailable -- Domain: Invoice, Company: My Company (SF), Applicability: Mandatory - Go to Manufacturing > Configuration > Work Centers - Open any work center and click on Analytic Distribution Before the fix, Internal is shown as Mandatory instead of Unavailable Removing the company from the applicability line confirms the issue opw-6404884 Forward-Port-Of: odoo/odoo#280312
The automated Click All test now skips the Website Shop menu to avoid getting stuck in a repeated page reload loop. This keeps build validation reliable and prevents long-running test timeouts that could delay releases.
Original PR description
Before this commit, every Click All build failed on the Website app:
FAIL: Subtest TestMenusAdmin.test_01_click_everywhere_as_admin
AssertionError: Script timeout exceeded
This happens because the Shop menu is an `ir.actions.act_url` on the current tab, so clicking it loads the website preview as a new page. Clickall resumes from the state it keeps in the local storage, but restarts the menu walk of the app at its first menu, so it reaches Shop again and the same menus are tested over and over, until the 1200 seconds script timeout.
This commit adds the menu to the Clickall blacklist. Master and saas-19.4 carry that entry from "[FIX] web: blacklist shop menu from Clickall to prevent infinite reload loop".
https://runbot.odoo.com/odoo/error/944407
Forward-Port-Of: odoo/odoo#286246Fixed an issue where an online store product page could automatically select the first multi-checkbox option after repeated refreshes. This prevents unintended product option choices and keeps the shopping experience consistent for customers.
Original PR description
**Steps to reproduce:** 1. Create a product. 2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio). 3. Publish the product and open its page on eCommerce. 4. Verify that no…
**Steps to reproduce:**
1. Create a product.
2. Add two attributes: multi-checkbox and any single-select type (e.g. Radio).
3. Publish the product and open its page on eCommerce.
4. Verify that no multi-checkbox option is selected by default.
5. Refresh the page twice.
**Issue:**
On the second page refresh, the first option of the multi-checkbox attribute is automatically selected, and the URL is updated with its parameter.
**Cause:**
- `_prepare_product_values` construct attribute combinations by mapping requested `attribute_values` query parameters line by line.
- When URL query parameters were present (e.g., set after the first refresh), the fallback logic `or ptal.product_template_value_ids.filtered('ptav_active')[:1]` treated unselected `multi_checkbox` attribute lines as missing required selections rather than empty selections, forcing them to default to their first active option.
**Fix:**
If no selection is provided for `multi_checkbox` line, return an empty recordset instead of falling back to the first active option.
opw-6494697
Forward-Port-Of: odoo/odoo#284798This fixes an issue where newly selected website themes could install without updating visible parts of the site, such as the header and footer. Theme setup now reliably detects the active website during installation, so the chosen design is applied as expected.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286221 Forward-Port-Of: odoo/odoo#283174
The tax return creation wizard now checks for duplicate returns only within the selected company. This prevents users working with multiple active companies from being incorrectly blocked by returns that belong to another company.
Original PR description
To reproduce the issue: 1) Create two companies in Belgium: A and B 2) Manually create a return for A before its opening date 3) Switch to company B, and keep A active as well 4) Try creating a return of the same type and at the same date as in 2) ===> The wizard blocks you and displays a warning saying there's already a return at this date. There is, but for another company. We fix that by properly filtering the company when searching for existing returns. Moving the _read_group inside the loop on self is okay here: we'll never compute that field for multiple wizards at once. Forward-Port-Of: odoo/enterprise#130303
Manual quantity-based quality checks on pickings can now be partially failed without blocking the operation. The fix ensures Odoo finds the related stock movement and keeps required quality check details when splitting failed quantities.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `quality_control` module - Create a picking order with a product - From the gear menu, create an on-demand Quality Check -…
Version:
--------
- 19.0+
Steps to reproduce:
-------------------
- Install `quality_control` module
- Create a picking order with a product
- From the gear menu, create an on-demand Quality Check
- Set the check to *Control per Quantity* and back to the picking
- Set the done quantity to 10
- Open the Quality Check wizard
- Try to fail 3 units
Issue:
------
Validating the partial failure raises a `ValidationError`:
- Missing required value for the field 'Team' (team_id)
The quality check split is not performed and the picking cannot be processed.
Cause:
--------
Quality checks created on-demand from the picking (via the gear menu) have
no associated `quality.point` or `stock.move.line` — only
`picking_id` is set at creation time.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L457
In `_move_to_failure_location()`, the `move_line` branch assumes
`check.move_line_id` is populated. Since it is empty for on-demand
checks, the split logic operates on an empty recordset.
The new quality check for the split is then created via:
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/quality.py#L493
At this point both `failed_move_line` (a copy of the empty move line) and
`check.point_id` are empty. `_get_check_values(False)` cannot derive
fields normally sourced from the quality point (`team_id`, `company_id`,
`measure_on`, `test_type_id`, etc.), causing the `ValidationError` on record creation.
Fix:
----
- If the quality check is not linked to a move line, find the matching move line
from the picking before splitting the failed quantity.
https://github.com/odoo/enterprise/blob/7d40d6b787511bf2fcbf581859ed2cd38ba3f658/quality_control/models/stock_move_line.py#L94-L97
- `_get_check_values()` normally takes values from a Quality Point.
Since on-demand quality checks do not have one, fill the missing
values (`team_id`, `measure_on`) from the original quality check instead.
This allows manually created quantity-based quality checks to be
split correctly after a partial failure.
---
opw-6428749
Forward-Port-Of: odoo/enterprise#126505Spreadsheet freeze actions now create the expected data loss prevention log entry. This improves audit visibility when protected spreadsheet data is made static, helping organizations track sensitive data handling.
Original PR description
Task: 6389096 Forward-Port-Of: odoo/enterprise#129607 Forward-Port-Of: odoo/enterprise#126461
Fixes an issue where changing the website header width could show an inaccurate live preview for several header styles. The setting now applies through the correct path for those headers, helping users avoid surprises when editing and saving their website design.
Original PR description
The header width option is not previewed properly on the following header templates: - `template_header_boxed` - `template_header_sales_one` - `template_header_sales_two` - `template_header_sales_three` - `template_header_sales_four` - `template_header_search` This happens because these templates are not compatible with the action `previewableWebsiteConfig` (their width can't be previewed by adding a single class). This commit fixes the problem by using the action `websiteConfig` instead of `previewableWebsiteConfig` when one of these templates is set. task-6420611 Forward-Port-Of: odoo/odoo#286292 Forward-Port-Of: odoo/odoo#282311
This fixes an issue where manually increasing the quantity on a timesheet invoice could prevent later timesheet entries from being billed. Businesses can now invoice future periods correctly while preserving refund-related behavior.
Original PR description
## Issue When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent…
## Issue
When a use rmanually increases the invoiced quantity on a timesheet invoice, subsequent timesheets logged in future periods can no longer be invoiced. The system assumes that the most recent logged hours are already covered by the previously over-invoiced amount, blocking the billing of the most recent timesheet entries.
## Steps to reproduce
1. Install *Sales Timesheet* (`sale_timesheet`)
2. Create a Product P
- Product Type: Service
- Invoicing Policy: Based on Timesheets
- Create on Order: (Project &) Task
3. Create an SO:
- Customer: Any
- Product: P (any quantity)
- Confirm
4. Record hours on the task created:
- 06/01/2026 (June 1st): 1 hour
- 07/01/2026 (July 1st): 1 hour
5. Create the invoice for the June timesheet entry (by setting a timesheets period when creating the invoice), then **change the quantity to any value strictly greater than 2** and confirm.
6. Create the invoice for July
7. **An "Invalid Operation" error appears, stating that there's nothing to invoice, even though the timesheet entry from July was never invoiced.**
## Cause
Since https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20, the computation of the quantity to invoice changed to include the difference between the quantity delivered and the quantity already invoiced. In the flow described by the steps to reproduce above, the quantity to invoice is larger than the quantity delivered, making the `qty_to_invoice` equal to `0.0`.
https://github.com/odoo/odoo/blob/626d31fa0191bfe7ca8e1fcf177357eeeb60f2c7/addons/sale_timesheet/models/sale_order.py#L331-L334
The reason for the fix above being the partial refunding of timesheet-related invoices, we can keep that solution when working with refunded invoices, and keep the previous behavior for other cases.
This solution solves the issue in the steps to reproduce above, but was also manually tested on the issues from https://github.com/odoo/odoo/commit/3b86ac3d180993239b63fd305ee0ba1f17f7eb20 and https://github.com/odoo/odoo/commit/64cf4afabd0c5ef040cf87fc6f3125fe0bb81bbb.
opw-6485674
Forward-Port-Of: odoo/odoo#286116
Forward-Port-Of: odoo/odoo#284470German DIN5008 invoices sent by post now place the sender, invoice details, and recipient address in the correct positions. This prevents misaligned printed mail layouts while leaving regular invoice layouts unchanged.
Original PR description
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer…
**Steps to reproduce:** - Install l10n_din5008 and Accounting. - Enable Snailmail from Accounting → Settings. - Create a German customer (Fiscal Country: Germany). - Create and post a customer invoice using the DIN5008 report layout. - Select Send by Post. - Enable Developer Mode and navigate to Settings → Technical → Email → Snailmail Letters. - Open the generated letter and send it. **Observed behavior:** The address blocks are incorrectly aligned when the DIN5008 report is rendered for snailmail. The information block and recipient address do not follow the expected vertical positioning. **Cause:** The DIN5008 layout previously applied vertical alignment rules to its table cells. These rules were removed while adapting the layout to the invoice table structure and its customizations, such as the position column and line numbering. While this alignment is no longer required for the regular DIN5008 invoice layout, the snailmail layout relies on it to correctly position the sender/invoice information and recipient address blocks. **Fix:** Add a `snailmail` class to the DIN5008 invoice section when `snailmail_layout` is present in the rendering context. Restore the required vertical alignment rules scoped to this class so they only affect snailmail reports, without changing the regular DIN5008 layout. **References** * **PR:** [#201225 – DIN5008 layout improvements](https://github.com/odoo/odoo/pull/201225) * **Ticket:** [6387869](https://www.odoo.com/odoo/project/49/tasks/6387869) opw-6387869 Forward-Port-Of: odoo/odoo#286056 Forward-Port-Of: odoo/odoo#285891
Mexican electronic invoice XML files (CFDI) are now correctly linked to vendor bill receipts created from expenses. This lets users see and validate the required tax document attachment instead of it being hidden in the database.
Original PR description
**Current behavior:** Currently, account moves created from expenses (type receipt) don't include the XML when it is a CFDI. Causing users cannot see their attachment even though it is created on DB. https://docs.google.com/videos/d/1eFSAA-wvUzPDwIJDeiS2dkne94lGM7QBxRfjN3HxaLw/play **Versions:** 19+ **Fix:** Implementing a new helper to identify those moves that can actually hold a CFDI document (for now, all `is_invoice()` documents + vendor bill receipt, `in_receipt`), so now, we include 'in_receipts' in _compute_l10n_mx_edi_cfdi_state_and_attachment, _compute_l10n_mx_edi_document_ids, _compute_l10n_mx_edi_update_sat_needed and l10n_mx_edi_cfdi_try_sat. As these documents might need to fetch SAT services as well. Task-id: [6397080](https://www.odoo.com/odoo/project/49/tasks/6397080) Forward-Port-Of: odoo/enterprise#129074 Forward-Port-Of: odoo/enterprise#126493
Combo choices with a negative extra price now display cleanly in POS and kiosk flows, without confusing double signs or misplaced minus signs. This helps staff and customers clearly understand discounted combo options at checkout or self-ordering.
Original PR description
When a combo choice has a negative extra price, the POS and Kiosk would incorrectly display a '+' sign in front of the negative price (e.g., '+ -0,30 €'). Additionally, depending on the currency formatting rules, a negative price might be displayed with the minus sign after the currency symbol (e.g., '$ -1.00'). This commit fixes this by conditionally displaying the '+' sign only when the extra price is strictly positive, and handling the minus sign manually to ensure it is always prepended correctly (e.g. '- $ 1.00'). task-id: 6226406 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283498 Forward-Port-Of: odoo/odoo#265210
When users reduce or remove column layouts in the HTML editor, empty columns are now discarded instead of leaving behind unnecessary blank paragraphs. Content in non-empty columns is preserved, and the editor still keeps one editable paragraph if all columns are empty.
Original PR description
#### Description of the issue this PR addresses: - When reducing the number of columns or removing a column layout, empty columns were previously unwrapped like any other column. - As a result, columns containing only placeholder paragraphs contributed empty paragraphs to the resulting content, even though they did not contain any meaningful user content. #### Desired behavior after PR is merged: - Fully empty columns are discarded when they are removed. - Non-empty columns continue to be merged as-is, preserving their content. - A single empty paragraph is still kept when all columns are empty to ensure the editor remains editable. - Rename `Remove columns` to `Remove column layout` and update its description to `Convert columns to regular content` to better reflect the operation. task-6296536 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284687 Forward-Port-Of: odoo/odoo#270220
This update corrects how Adyen payment details are read from incoming payment data. It helps ensure payments are matched and processed using the right information, reducing the risk of failed or incorrect payment handling.
Original PR description
opw-6512723 Forward-Port-Of: odoo/odoo#284773
Removed an obsolete behind-the-scenes setting from the Philippines tax report wizard view. This keeps the screen compatible with newer Odoo versions without changing what users see or how the wizard works.
Original PR description
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly…
The `modifiers` attribute was used in older Odoo versions to define field properties (invisible, readonly, required, etc.) Since the field already declares these same properties directly [state](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L150-L155) , [amount_tax_signed](https://github.com/odoo/odoo/blob/14.0/addons/account/models/account_move.py#L229)
(e.g. `invisible=...`, `readonly=...`), the `modifiers` attribute is redundant and serves no purpose.
This attribute was never added manually by us — it was auto-generated by Odoo Studio when the default view was created. Studio's default views inject `modifiers` alongside the direct attributes. [Here](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-dfebe5a93e1b8880e88268b024be4c6f106d144b20298d7bb6c4ae09a18bafd0L67-L145)
Also the `modifiers` attribute was fully simplified [removed](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) starting from version 17.0, where views rely exclusively on direct attribute expressions (`invisible`, `readonly`, `required`) instead of the `modifiers` JSON encoding [main Patch](https://github.com/odoo/odoo/pull/104741) Keeping it around in the arch is therefore dead code with no effect.
However it needs to give the error on 17.0+ like this
```
ERROR LOG:
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_NOELEM: Expecting an element data, got nothing
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_INVALIDATTR: Invalid attribute modifiers for element field
<string>:1:0:ERROR:RELAXNGV:RELAXNG_ERR_EXTRACONTENT: Element tree has extra content: field
```
As the modifer has been remove from the field [common.rng](https://github.com/odoo/odoo/pull/104741/changes/975e875046691c898e8c1acb87d3626cd299e5aa#diff-849f1ed2a35a8b0b9cdd67f8e34de5d2ea7bf928103a83828587ba7ec14a62e4L52) RelaxNG schema but modifiers set on fields here root tag is **form**, and the modifiers sit on fields inside a nested list. And Form views aren't RNG-validated from 17.0 till now —
[@validate('calendar', 'graph', 'pivot', 'search', 'list', 'activity')](https://github.com/odoo/odoo/blob/f0e58b9324af18d0cf0264aec2886d098e997f03/odoo/tools/view_validation.py#L314) has no form, and there's no [form_view.rng](https://github.com/odoo/odoo/tree/19.0/odoo/addons/base/rng).
Current senario
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer: it show the same view because of field property
<img width="998" height="415" alt="image" src="https://github.com/user-attachments/assets/1a678c8f-8401-4e12-826f-9e98f6f2fe20" />
After removing the modifer still it shows the **modifiers="{'readonly':true, 'required':true}"** because the modifer is stay in the 14.0 but the 17.0 onwards it was not please see the scrrenshot its field preprty always.
<img width="1003" height="462" alt="image" src="https://github.com/user-attachments/assets/5e833924-b17c-417f-9e63-5a01c185f588" />
This Fix removes the unused `modifiers` attribute from the view arch, keeping only the direct attribute already present, with no functional change to the view's behavior.
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#283310
Forward-Port-Of: odoo/odoo#279976Installing the Polish bank verification module no longer tries to process all existing payments at once. This avoids crashes for companies with large payment histories and makes setup more reliable.
Original PR description
account.payment model computes every record l10n_pl_verification_id at module installation (l10n_pl_bank_verification), causing crash in case of db with a large number of records wrong method name correction: _auto_init instead of init and call super after creating the db column see odoo/odoo#282504 Forward-Port-Of: odoo/odoo#285968
The website translations endpoint now bypasses website-specific routing because it already receives the requested language directly. This prevents unwanted language redirects and cookie conflicts, helping translations load more reliably for users.
Original PR description
/website/translations does not require request.website or language redirection logic as `lang` is passed explicitly. Drop `website=True` to prevent unexpected language redirects and cookie conflicts. Backport of 4faddd8b44 (odoo/odoo#269325). runbot-231758 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281738
The expense screen now uses the correct status name, “approved,” for approved expense records. This prevents confusion for users reviewing or managing employee expenses.
Original PR description
Use the correct state name (approved) @Tecnativa --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285950
The website editor no longer shows a theme background option for tab sections because that option did not work reliably in this version. This avoids users selecting a styling choice that would not apply as expected, making the page-building experience clearer.
Original PR description
The theme background options (`o_cc` classes) on the `s_tabs` snippet's tabs doesn't work since 18.4 (html_builder refactor). It was not supported either in previous versions. We decided to fix it so it would be useable in master (20.0) but leave stable versions as is, by restraining the available tabs and removing the theme one. task-5951656 Forward-Port-Of: odoo/odoo#277528
Italian withholding tax returns submitted in quarter-ending months no longer trigger the periodic VAT return export by mistake. This prevents failed exports or incorrect LIPE files from being attached to the wrong return, improving reliability for Italian tax filings.
Original PR description
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the…
In Italy the periodic VAT return (LIPE) is filed quarterly, so `is_quarter_month` gates the XML export wizard on March, June, September and December. That field only looks at the date, never at the kind of return, so every Italian return locked on a quarter month was treated as a LIPE. Submitting the withholding tax return therefore opened the LIPE export wizard. Depending on the record the wizard receives, it either crashes while reading the VP lines missing from the withholding report, or silently generates a LIPE file and attaches it to another return. Add an `is_lipe_return` field telling whether the return actually produces the LIPE. Steps to reproduce: - Install `l10n_it_xml_export` and `l10n_it_edi_withholding_reports` on an Italian company with monthly returns - Open Accounting > Reporting > Tax Return - Review and submit the withholding returns up to February - Review then submit the March withholding return --> The LIPE export wizard opens, and the export fails on the withholding report. opw-6255016 Forward-Port-Of: odoo/enterprise#126676 Forward-Port-Of: odoo/enterprise#125263
The website editor search field now shows a hand cursor when users hover over the clear icon in browsers that display it. This small visual cue makes it clearer that the icon can be used to quickly remove search text.
Original PR description
Steps to reproduce: - Open the website editor. - Open the "Insert a block" dialog. - Enter text in the search bar. - Hover over the clear icon. => The cursor does not indicate that the icon is clickable. Before this commit, the search clear icon kept the default cursor. After this commit, the clear icon uses a pointer cursor to indicate that it is clickable. Note that Firefox does not natively add this clear icon to search inputs, unlike Chrome. This fix only affects browsers that render it. task-6259086 Forward-Port-Of: odoo/odoo#283435
The Romanian tax return list now shows the specific D300 declaration name instead of the generic label "Tax". This makes it easier for users to identify the correct return when preparing Romanian tax reporting.
Original PR description
Before this commit: When generating a Romanian tax return, one of the return types in the list was labeled "Tax", which was too generic to know which specific tax declaration it referred to. After this commit: The tax return is now renamed to "D300", making it easy to identify this return in the list instead of seeing a generic "Tax" label. task - 6388087 Forward-Port-Of: odoo/enterprise#124583
UPS deliveries could be rejected when an invoicing address did not have its own name. This fix uses a fallback name so shipments can be accepted by UPS in that common customer setup.
Original PR description
Issue ----- By default, invoicing addresses of existing partners are created without a name. This leads to the deliveries being rejected by UPS. Steps to reproduce ----- - Set Up UPS - Create a Customer - Create an invoicing address with no name - Create a SO for the partner & confirm - UPS delivery - Open the picking and confirm it > UPS rejects the shipment /!\ I could not reproduce in testing environment, so this is based off user steps in their production DB. /!\ Cause ----- The partner being used in `_set_invoice` was changed in #119747 but this use case was missed due to the error not occuring in test mode. ----- Ticket: opw-6485164 Forward-Port-Of: odoo/enterprise#128933
This fix stops Odoo live chat embeds from blocking browser keyboard shortcuts such as Alt+D when there are no Odoo shortcut overlays to show. Users on external websites with embedded live chat keep normal browser behavior, while Odoo shortcut overlays still work where available.
Original PR description
Description of the issue/feature this PR addresses: When `im_livechat` (or any page) boots the OWL web stack with no `[data-hotkey]` / `withOverlay` targets, pressing Alt still called…
Description of the issue/feature this PR addresses: When `im_livechat` (or any page) boots the OWL web stack with no `[data-hotkey]` / `withOverlay` targets, pressing Alt still called `preventDefault()` in `hotkey_service`. That blocked browser shortcuts such as Alt+D (focus address bar) on websites that embed the livechat scripts. See https://github.com/odoo/odoo/issues/267928 Current behavior before PR: - Pressing the overlay modifier (Alt, or Ctrl on macOS mapped to `"alt"`) always set `overlaysVisible = true` and called `preventDefault()`, even when there were no hotkeys to overlay. - A follow-up key (e.g. D while Alt is held) then also hit `preventDefault()` because overlays were considered visible. - Loading `/im_livechat/loader/...` + `assets_embed.js` on an external site therefore broke browser Alt shortcuts. Desired behavior after PR is merged: - `addHotkeyOverlays` returns whether overlays were actually displayed. - `preventDefault` on the overlay modifier runs only when there is at least one overlay target. - Pages with no hotkeys (typical livechat embed) leave browser shortcuts alone. - When hotkeys exist, Alt still shows overlays and cancels the default, same as before. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284145
The unread ticket filter now correctly treats tickets as needing attention when the latest message is an automatic system message, such as one from OdooBot. This helps support teams avoid missing newly submitted website tickets that were previously hidden from the unread view.
Original PR description
**Steps to reproduce:** - Install website_helpdesk. - Create a team and enable website form. - Create a ticket through the website. - Apply the Unread filter. **Issue:** system generated message, such as message authored by OdooBot, were not considered when determining whether a ticket was unanswered. **Cause:** the search method only considered the last message when its author matched the ticket's partner. **Fix:** Consider a ticket unanswered when the last message's author matches the ticket's partner, or when the last message is an automatic system generated message. task-5138678 Forward-Port-Of: odoo/enterprise#130100
This update fixes an automated test for Indonesian e-Faktur invoices by explicitly applying the required tax instead of depending on defaults that may vary between builds. It helps keep invoice download checks reliable and prevents false build failures related to missing taxes.
Original PR description
Issue: In some build, when creating the invoice line it did not assign the default tax so it raise an error when downloading efaktur Fix: Assign the tax line manually in the unit test instead of relying on default taxes issue-[946227](https://runbot.odoo.com/odoo/error/946227) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents Odoo from showing repeated error dialogs when the browser storage used for the unread message badge is cleared, blocked, or unavailable. The unread badge is treated as optional, so messaging and the rest of the interface continue working normally even if the badge count cannot be saved.
Original PR description
Description of the issue/feature this PR addresses: The unread counter feeding the PWA app badge is written to the `odoo-mail-unread-db` IndexedDB database, through a connection opened once, at…
Description of the issue/feature this PR addresses: The unread counter feeding the PWA app badge is written to the `odoo-mail-unread-db` IndexedDB database, through a connection opened once, at module load, and cached for the life of the page by the bundled idb-keyval (3.2.0), which cannot reopen it. When the browser drops the origin's storage (eviction under disk pressure, site data cleared, a privacy extension purging it), that connection is closed for good, and as `updateAppBadge()` discards the promise returned by `idbKeyval.set()`, the rejection reaches the user as a client error dialog. Reported in production on a backend tab left open overnight (Firefox, 19.0): ``` UncaughtPromiseError > InvalidStateError Uncaught Promise > IDBDatabase.transaction: Can't start a transaction on a closed database ``` Reproduced on a demo database below, with `?debug=assets` so that the stack points at the source: lines 23 and 24 of the vendored idb-keyval are the `db.transaction()` call of `_withIDBStore`, on the connection cached at module load. <img width="1600" height="590" alt="error-dialog-debug" src="https://github.com/user-attachments/assets/e2b1aa46-501a-43d4-b4c0-20def1f529ef" /> Current behavior before PR: 1. log into the backend and leave the tab open 2. in the devtools, Application > Storage, tick *only* "IndexedDB" and click "Clear site data", as the browser itself does when it evicts the origin (the session cookie is left untouched, so the tab keeps working) 3. receive a message, or do anything else that changes the unread counter The dialog opens, and opens again on every counter update for the whole life of the tab, since the dead connection is never replaced; the counter is not saved any more either. Two variants of the same code: the write also rejects, without anything being cleared, when the origin runs out of storage quota (`QuotaExceededError`), and when the browser forbids storage for the origin, `indexedDB.open()` throws during module evaluation, so `store_service_patch.js` fails to load entirely. Desired behavior after PR is merged: The store is opened lazily, dropped whenever saving the counter fails, and the write is retried once on a new connection: a single counter update after the connection was closed saves it again. Opening the database is guarded too, for the synchronous throw. When the retry fails as well the error is ignored, the app badge being cosmetic. `mail/static/tests/web/app_badge.test.js` covers the retry, the recovery of a permanently closed connection, and the database that cannot be opened at all. The three tests fail on the current code with the uncaught `IDBDatabase.transaction` error. Introduced in 19.0 by c04c4cb715902fe95618a15e18233cd001bdb304, and identical from saas-19.1 to master, hence this PR against 19.0. The corporate CLA for ERPVibe Limited is submitted in #283477. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283480
The Helpdesk team card now displays the email alias in better alignment with the team name. This small visual fix makes the interface cleaner and easier to read for users managing helpdesk teams.
Original PR description
In this commit, we remove the margin before the mail alias, ensuring aligment within the helpdesk team card. task-6416578 Forward-Port-Of: odoo/enterprise#129865