Thursday, September 3, 2026
47 changes · saas-19.3
Resolved issues and error corrections
Updated Point of Sale stock test flows so customer searches can load matching records from the server when they are not already cached. This prevents automated test failures in databases with many demo customers and helps keep validation of stock-related POS workflows reliable.
Original PR description
When running tests with demo data, the partner list is populated with many records, causing 'Partner Test 1' to fall outside the initial 100 loaded partners in the PoS session cache. Because clickCustomer defaulted to pressEnter=false, searching in the UI filtered the in-memory cache and displayed 'No customers found, press Enter to load more.', but never dispatched the Enter key to fetch the partner from the backend, timing out the tour step. Pass pressEnter=true in pos_stock customer selection tours so that the Enter key is dispatched and the partner is fetched from the server via RPC. runbot-error: 242001 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixes an issue where some website header layouts showed an inaccurate preview when changing the header width setting. The option now applies in a way that matches the selected header template, reducing confusion while editing website designs.
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
The certificate setup flow no longer shows an error banner when a key file is added without a password. Users will only see the warning when they entered a password and it is actually incorrect, reducing confusion during certificate configuration.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285744 Forward-Port-Of: odoo/odoo#283589
This fix prevents the Mail reply box from staying open when a user presses Escape while mention suggestions are loading. It makes the reply discard action more reliable, especially under slower server conditions.
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
Combo options with a negative extra price now show the discount amount clearly in POS and kiosk screens. This avoids confusing price labels such as '+ -0,30 €' and makes discounted combo choices easier for customers and cashiers to understand.
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
This fixes an issue where resize controls in the website builder could be hidden behind the sidebar when editing animated page elements. Users can now clearly see and resize selected content even while scrolling, making page editing more reliable.
Original PR description
Steps to reproduce: - Drop a few snippets to make the page scrollable - At the bottom, drop the `s_three_columns` snippet - Click on the last Card - Add an animation "onScroll" (Effect - Slide, Intensity - 100) - Scroll top slightly to hide a part of the card behind the sidebar => The resize overlay is partially hidden The elements `.hb-row` have a z-index of 2, so they appear in front of the overlay which has a z-index of 1. It was decided to fully show the overlay to allow resizing. Keeping the overlay visible in front of the sidebar also allow the user to see where animated element is. task-6476269 Forward-Port-Of: odoo/odoo#283842 Forward-Port-Of: odoo/odoo#282796
This fix ensures that selected website themes are fully applied during setup, including visible changes such as headers and footers. It prevents theme installation steps from being skipped, giving users the expected website appearance after choosing a theme.
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
Analytic plan applicability now keeps the default setting on screens that are not tied to a specific business area, such as Work Centers or Employees. This prevents invoice-specific company rules from incorrectly making analytic fields mandatory in unrelated workflows, reducing user confusion and data-entry friction.
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
This fixes the website translations endpoint so it no longer applies website-specific language redirection rules when a language is already provided. It helps prevent unexpected redirects and cookie conflicts for users loading translations.
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
Product pages now keep multi-checkbox options unselected unless shoppers choose them. This prevents confusing automatic selections and unwanted URL changes after refreshing a product page.
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 fix ensures Adyen payment notifications use the correct values from the data they receive. It helps keep payment processing and transaction status updates accurate for businesses using Adyen.
Original PR description
opw-6512723 Forward-Port-Of: odoo/odoo#284773
The automated Click All test now skips the Website Shop menu to avoid repeatedly reloading the website preview. This prevents long-running test timeouts and keeps build validation reliable for the Website app.
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#286246Salary offers can now be created for employees whose new contracts start in the future, even when they have a current contract ending today. This prevents an incorrect date overlap error and helps HR teams prepare future contract offers without manual workarounds.
Original PR description
Before this commit, creating a salary offer for a contract starting in the future raised a ValidationError on contract dates if the employee had an active contract ending today. This occurred because the salary simulation fallback logic defaulted to using today's date for the default contract start date, causing the simulation to overlap with the current running contract. This commit uses the target contract version's start date instead of today's date, preventing contract date overlap validation errors during offer generation. Task: 6502960
Vendor bill XML imports now handle cases where the supplier country is missing from the file. When possible, the system uses the country already saved on the related partner record instead, preventing unnecessary upload errors for accounting users.
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
This fixes a billing issue where manually increasing a timesheet invoice could prevent later timesheets from being invoiced. Businesses can now invoice future time periods correctly while preserving expected behavior for refunds.
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#286301
Forward-Port-Of: odoo/odoo#284470Planning managers who do not have HR permissions can now publish scheduled shifts successfully. The update ensures the system can still find the relevant employee information needed to send publication notifications, so staff receive their planning updates as expected.
Original PR description
Steps: - As a planning manager without HR right - Schedule planning slots - Publish them Actual result: - employee_ids is empty as user don't have access HR - nothing is sent Expected result: - Planning publication is well sent Similar to: https://github.com/odoo/enterprise/pull/127503
The return creation wizard now checks for existing returns only within the relevant company. This prevents users working across multiple 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
This fixes an issue in Belgian payroll where occupation attestations could fail or be calculated incorrectly when an employee contract had no end date. It helps ensure payroll-related attestations handle ongoing contracts reliably.
Original PR description
A check was missing if the contract end date was false
The Helpdesk SLA Status Analysis report now measures Hours Open from ticket creation to closing, matching the Ticket Analysis report. This fixes misleading SLA reporting where tickets assigned immediately could show no open time, giving managers a more accurate view of how long issues remain unresolved.
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 ensures that when a refund is created in Italian POS with a fiscal printer, users are sent to the payment page for the refund order instead of the product screen or original order. This prevents confusion at checkout and helps staff complete refund transactions correctly.
Original PR description
**Issue**: 1. From versions 18.4 to 19.1 inclusive, the system redirects to the product screen; 2. From version 19.2 onward, the redirection targets the payment page of the original order instead of the refund order. **Expected behavior**: The system navigates to the payment page for the refund order. **Steps to reproduce**: - Set up an Italian fiscal printer; - Open a POS session and process an order; - Create a refund for the order. [Ticket link](https://www.odoo.com/odoo/project/49/tasks/6499079) opw-6499079 Forward-Port-Of: odoo/enterprise#130044 Forward-Port-Of: odoo/enterprise#129758
This fixes the DIN5008 German invoice layout when documents are sent by post, ensuring the recipient and information blocks are positioned correctly for snailmail. Regular DIN5008 invoices are unchanged, reducing the risk of layout regressions while restoring proper postal formatting.
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
This fix ensures a Canadian payment validation test checks results in a consistent order. It helps avoid false test failures in automated checks, supporting smoother releases without changing customer-facing 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
Belgian payroll now correctly treats public holidays as unpaid when they fall after the guaranteed sick pay period, even if a new medical certificate starts that day. This prevents employees from being overpaid due to timing or timezone differences in leave records.
Original PR description
Steps to reproduce: - Employee on full-time sickness certified month by month (one hr.leave per medical certificate), guaranteed salary period already exhausted. - Compute payroll for the month whose public holiday falls on the first day of a new certificate. - Public holiday work entry stays paid, every other day that month is correctly unpaid. Cause: the 30-day lookback compared exact datetimes instead of calendar dates, so a certificate starting the same day as the holiday but later in clock-time got excluded. Also ignored timezone: date_from is stored in UTC and needs localizing before taking .date(). Fix: compare local calendar dates via hr.leave's own request_date_from/request_date_to instead of raw UTC datetimes. Added a regression test for the split-certificate case. Task 6512860
Additional automated checks were added to make sure suggested timesheet entries are linked to the correct helpdesk tickets and calendar-related work items. This helps reduce the risk of incorrect time tracking suggestions reaching users.
Original PR description
task: 6475133
Refund payslips are now recalculated correctly whenever payroll worked days or pay lines are recomputed, not only during a reset. This helps prevent payroll refund amounts from becoming inaccurate after updates or recalculations.
Original PR description
Instead of only resetting correctly the refund payslip in the reset, ensure that anytime we recompute worked days or lines, the refund is correctly computed.
Canteen costs are now assigned to the first payslip in the month that includes a paid amount when an employee has multiple contracts. This prevents the cost from appearing on the wrong payslip and helps Belgian payroll stay accurate.
Original PR description
In case of multiple contracts for a single month (and then multiple payslips), the canteen cost must appear in the first payslip that have a paid amount.
This fixes a manufacturing issue where Odoo could show a false consumption warning for serial-tracked components bought on demand. Users can now complete affected manufacturing orders without unnecessary warning prompts when the component quantity matches what was expected.
Original PR description
Steps to reproduce the bug: - Warehouse configured for 2-Step Manufacturing - Component "C1": - Routes: MTO + Buy - Tracking: By Unique Serial Number - Create a Finished product: - Route: Manufacture…
Steps to reproduce the bug:
- Warehouse configured for 2-Step Manufacturing
- Component "C1":
- Routes: MTO + Buy
- Tracking: By Unique Serial Number
- Create a Finished product:
- Route: Manufacture
- Tracking: By Unique Serial Number
- BoM:
- component "C1": 1 unit
- Create and confirm the Manufacturing Order
- Generate/assign the serial number for the finished product immediately, before the related purchase order is even confirmed
- Confirm the Purchase Order
- Receive the component
- Transfer the component to WH/Pre-Production
- Click Produce All
Problem:
A Consumption Warning was displayed stating that the consumed quantity differs from the expected quantity, even though the consumed quantity was exactly equal to the BoM quantity and no manual quantity change was performed. Clicking "Set Quantities & Validate" completed the MO successfully, hiding the inconsistency.
`_get_consumption_issues()` only counts a raw move's quantity as "consumed" when `move.picked` is `True`
[(odoo/addons/mrp/models/mrp_production.py#L1791)](https://github.com/odoo/odoo/blob/19.0/addons/mrp/models/mrp_production.py#L1791).
Generating the finished product's serial number calls `_set_qty_producing()`
[(odoo/addons/mrp/models/mrp_production.py#L1402)](https://github.com/odoo/odoo/blob/19.0/addons/mrp/models/mrp_production.py#L1402).
, which itself only sets `move.picked = True` when `move.quantity` is truthy
[(odoo/addons/mrp/models/mrp_production.py#L1443)](https://github.com/odoo/odoo/blob/19.0/addons/mrp/models/mrp_production.py#L1443).
At that point the MTO component had not been received yet, so `move.quantity` was still 0 and `picked` was never set. Once the component was later received and transferred to Pre-Production, `_action_assign()` correctly reserved the raw move (`quantity` became correct), but nothing ever went back to flip `picked` to `True`, since `_set_quantities()`
[(odoo/addons/mrp/models/mrp_production.py#L2932)](https://github.com/odoo/odoo/blob/19.0/addons/mrp/models/mrp_production.py#L2932).
only calls `_set_qty_producing()` again when `qty_producing` is still falsy, which was no longer the case. `_get_consumption_issues()` therefore still counted the consumed quantity as 0 against the expected BoM quantity.
Solution:
In `pre_button_mark_done()`, for auto productions (single unit being produced), after `_set_quantities()` runs, also mark as `picked` any non-manual-consumption raw move that is not yet `picked` but whose reserved `quantity` already exactly matches its own `product_uom_qty`. This is scoped to auto productions only, since on a multi-unit production a raw move's aggregate `quantity` can equal its `product_uom_qty` by coincidence (reservation for future backorder steps) even though only part of it is meant to be consumed for the current step.
opw-6421531
Forward-Port-Of: odoo/odoo#285405
Forward-Port-Of: odoo/odoo#281258Mexican electronic tax documents attached to expense-generated vendor receipts are now correctly visible to users. This ensures employees and accounting teams can access the CFDI XML files already stored in the system and allows the related SAT status checks to run for these receipts.
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
This fixes an issue in the HTML editor where pressing Enter in a bullet list item that also contained a table did not split the list correctly. Users can now edit lists with embedded tables more naturally, while preventing accidental removal of mixed-content list items from the list.
Original PR description
### Steps to reproduce: - Insert a bullet list - Inside of the list, insert a table - Write before and/or after the table (in the same list item) - Press enter before and/or after the inserted text - Notice that the bullet is not split like in a normal list ### Root Cause: - On Enter, list plugin checked whether the list item contained unsplittable element. Since the table was inside the list item, it always treated the list item as unsplittable, even when the cursor was outside the table. As a result, the list item could never be split. ### Solution: - Instead of checking the whole list item, walk up from the split target to the list item and look for an unsplittable element along the way. This allows the list item to split normally when the cursor is outside the unsplittable. task-6449843 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284711 Forward-Port-Of: odoo/odoo#280903
This fix ensures that freezing a spreadsheet document is recorded in the data loss prevention log. It helps businesses maintain a more complete audit trail for sensitive spreadsheet activity.
Original PR description
Task: 6389096 Forward-Port-Of: odoo/enterprise#129607 Forward-Port-Of: odoo/enterprise#126461
Italian withholding tax returns submitted in quarterly months no longer trigger the periodic VAT return export by mistake. This prevents crashes and avoids generating or attaching the wrong LIPE file to non-VAT returns.
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
This fixes how the HTML editor handles removed or reduced column layouts by dropping columns that only contain empty placeholder content. Users will get cleaner resulting content, while meaningful column content is still preserved and the editor remains usable when everything is 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
The expense app now uses the correct status name, “approved,” in its views. This avoids confusing wording for users reviewing or managing expense reports and keeps the interface aligned with the actual workflow state.
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 Shopee sales connector now handles shipment label errors within the affected batch instead of stopping the full scheduled process. This helps ensure remaining shipment batches continue to be processed even when Shopee returns incomplete label data for some orders.
Original PR description
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch shipment labels for multiple batches of shipments. If some shipments do not contain the required data in the Shopee API…
Currently, an error occurs when the `sync_shopee_pickings` cron tries to fetch
shipment labels for multiple batches of shipments. If some shipments do not
contain the required data in the Shopee API response, the error causes the
cron to stop, preventing the remaining batches from being processed.
Error:
`ValueError: KeyError('status') while evaluating 'model._sync_shopee_pickings()'`
This issue was introduced by a recent refactoring commit [1] focused on linting
and formatting the Python file. The commit replaced the generic `Exception`
with `UserError` when handling errors during batch label printing.
As a result, errors other than `UserError` are no longer handled at the batch
level. When such an error occurs, the entire cron process stops instead of
failing only the affected batch and continuing with the remaining batches.
This commit fixes the above issue by handling generic `Exception` during
shipment label generation, ensuring that the error is handled for the
affected batch while the remaining batches continue to be processed.
[1]: https://github.com/odoo/enterprise/commit/cfe5d947579739ad770ac3f1525ce157af530846#diff-e072c3ecf980add685bb4a4f25cf2b0ab5d4625988e4afc2c4d4faeae687ca88R199
sentry-7685943988Forum information links are now treated as regular text links in the website editor instead of buttons. This prevents irrelevant button styling options from appearing, making forum page editing clearer and less confusing.
Original PR description
Steps to reproduce: - Go to a forum page. - Open the website editor. - Select the "About this forum" link in the sidebar. => Button styling options are shown for a regular link. Before this commit, forum information links used button classes, which made the editor expose button styling options for them. After this commit, the `btn`, `btn-sm`, and `btn-link` classes are replaced with `small` so the editor treats these elements as regular links on desktop and mobile. task-6259086 Forward-Port-Of: odoo/odoo#283156
The website editor’s block search field now shows a pointer cursor when users hover over the clear icon in browsers that display it. This small usability fix makes it clearer that the icon can be clicked to clear the 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 UK CIS report now correctly includes payment information for receipts that use CIS taxes, matching the behavior already available for vendor bills. This helps businesses keep CIS reporting complete and accurate when recording supplier receipts.
Original PR description
With the l10n_uk_reports_cis module installed: - Create a vendor bills and add a CIS tax --> This vendor's bills appear correctly in the report. - Create a receipt and add a CIS tax --> This type of bill appears in the report, but the payment is not showing up. opw-6282548 Forward-Port-Of: odoo/enterprise#127807 Forward-Port-Of: odoo/enterprise#124043
The Romanian tax return previously shown as “Tax” is now labeled “D300”. This makes it easier for users to identify the correct Romanian declaration when choosing a return type.
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
This fixes an issue where pages using Odoo live chat could block common browser keyboard shortcuts such as focusing the address bar with Alt+D. The change keeps Odoo shortcut overlays working when available, while leaving browser shortcuts untouched when there are no Odoo shortcuts to show.
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
This fix prevents the Polish bank verification module from trying to process every payment record during installation. It helps avoid installation crashes for companies with large payment histories, making module 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
This fixes an internal automated test for Indonesian e-Faktur so it no longer depends on default tax settings being applied automatically. The change helps keep quality checks stable and prevents false build failures around e-Faktur invoice downloads.
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 Forward-Port-Of: odoo/odoo#285902
UPS shipments could be rejected when a customer's invoicing address did not have its own name. The update uses a fallback name for the billing contact, helping ensure shipments can be confirmed successfully in UPS delivery flows.
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
The website editor no longer shows a theme background option for tab sections when that option does not work in this version. This prevents users from selecting a setting that would have no effect, making page editing clearer and less confusing.
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
This fixes accrued expense entries for purchase products that are billed based on ordered quantities. Confirmed purchase orders can now generate the expected accruals even before goods are received, improving accounting accuracy for month-end reporting.
Original PR description
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `stock`, `purchase`, and `accountant` - Create a storable product with: - Tracking Inventory enabled - Control Policy set…
Version: -------- - 19.0+ Steps to reproduce: ------------------- - Install `stock`, `purchase`, and `accountant` - Create a storable product with: - Tracking Inventory enabled - Control Policy set to **Ordered Quantities** - Create and confirm a Purchase Order with some unit price - Do not receive or invoice the order - From the Purchase Order gear menu, click **Accrued Expense Entry** Issue: ------ The Accrued Expense Entry wizard opens, but no accounting lines are generated. For products invoiced on **Ordered Quantities**, the ordered quantity should already be accrued even though nothing has been received. Cause: ------ This issue was introduced after this changes [commit](https://github.com/odoo-dev/odoo/commit/81f25bc57b8433a65bf33950c64dc7582240a229) Previously, the accrual wizard relied on the stored `qty_to_invoice` field, whose computation already respected the product's Control Policy. For products invoiced on **Ordered Quantities**, `_compute_qty_invoiced()` computes the quantity to invoice from the ordered quantity: https://github.com/odoo/odoo/blob/810a02a577c2811dc5c12f0abf45eebb9cf96d00/addons/purchase/models/purchase_order_line.py#L147-L152 The refactoring replaced this logic with the new `amount_to_invoice_at_date` field, which always computes the invoicable quantity as: `qty_received_at_date - qty_invoiced_at_date` https://github.com/odoo/odoo/blob/65dbcabcd243abf24d6d3c3788d2caff66485790/addons/purchase/models/purchase_order_line.py#L282-L285 This formula ignores the product's Control Policy. For products invoiced on Ordered Quantities, before any receipt: `qty_received_at_date` = 0 `qty_invoiced_at_date` = 0 therefore: `amount_to_invoice_at_date` = 0 The Accrued Expense wizard filters out lines whose `amount_to_invoice_at_date` is zero: https://github.com/odoo/odoo/blob/65dbcabcd243abf24d6d3c3788d2caff66485790/addons/account/wizard/accrued_orders.py#L168-L178 As a result, the purchase order line is excluded entirely and the wizard produces no accounting entries. The same assumption is also used later in `account.accrued.orders.wizard._compute_move_vals()` when computing tax-included amounts, causing incorrect accrual values for Ordered Quantities products whenever receipts and invoices differ. Fix: ---- Introduce `_get_qty_to_invoice_at_date()`, mirroring the existing purchase_method logic used by _compute_qty_invoiced(). The helper returns: product_qty - qty_invoiced_at_date for Ordered Quantities products; `qty_received_at_date` - `qty_invoiced_at_date` for Received Quantities products. Now products invoiced on `Ordered Quantities` become accruable as soon as the Purchase Order is confirmed; --- opw-6290782 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284507 Forward-Port-Of: odoo/odoo#276435
The Helpdesk unread ticket filter now includes tickets where the latest message was an automatic system message, such as one from OdooBot. This helps support teams avoid missing customer tickets that still need attention after being created through the website.
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
Basic point-of-sale receipts for Peruvian companies now hide additional electronic invoicing details, such as the amount in words, that are intended only for full receipts. This keeps basic receipts shorter and aligned with the selected receipt format.
Original PR description
Step to reproduce - install l10n_pe_edi_pos with demo and switch to PE company - from settings> "Signature Provider" set it to SUNAT - create a pos, enable "Basic Receipt" from settings - open pos…
Step to reproduce - install l10n_pe_edi_pos with demo and switch to PE company - from settings> "Signature Provider" set it to SUNAT - create a pos, enable "Basic Receipt" from settings - open pos and fulfill a order - from feedback screen, print > print basic recipt Observation: - `Amount In Word` is visible in basic receipt, we should not show such info in basic receipt Cause: - commit [1] introduces the template `l10n_pe_edi_pos.pos_order_receipt`, which adds the info block to the receipt using xpath `<xpath expr="//div[contains(@t-if, 'use_self_invoicing')]" position="before">` - this inserts the block before the [target div](https://github.com/odoo/odoo/blob/1ace23afe8a937fc1dc53879f33ca591fd5d25b8/addons/point_of_sale/receipt/pos_order_receipt.xml#L70-L86), which is independent of the `basic_receipt` flag, causing the block to always be visible [1] https://github.com/odoo/enterprise/commit/a0c4f841cde0fcfda0a0c57f865f0eff6b6d6afe Fix: - place the block so it is shown only when `basic_receipt` is false - update the xpath expression to `prices` div ( here `basic_receipt` is false `//div[@name='prices']` with `position="inside"` After fix (for full receipt) <img width="257" height="349" alt="image" src="https://github.com/user-attachments/assets/3932cae1-3ceb-42ad-9ce4-16a9bd4fea7d" /> opw-6383358 Forward-Port-Of: odoo/enterprise#125118
This fix prevents users from seeing repeated error popups when the browser clears or blocks the storage used for unread message badge counts. The unread badge may fail to update in those rare storage situations, but the main Odoo interface will continue working normally.
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