Daily updates from Odoo
Tuesday, July 7, 2026
12 changes · 17.0
Enhancements to existing features
Attachment deletion is now much faster for companies using Chilean electronic invoicing and stock documents. This reduces delays during cleanup operations on large databases, improving system responsiveness without changing user workflows.
Original PR description
## The problem Deleting attachments checks foreign key triggers. Lookups in `account_move` and `stock_picking` tables for `ir_attachment` related fields coming from `l10n_cl_edi` overrides were slow due to missing indexes. ## The solution Added needed indexes to optimize triggers' lookups. ## Benchmark Time benchmark (deleting attachments from a customer database with 224K account moves and 204K stock pickings): |# of rows|Time (Before)|Time (After)| |----------|--------------|-------------| 100 | 29s | 16ms 1000 | 285s | 300ms OPW-6331845
Attachment deletion is now much faster for Chilean electronic invoicing and stock documents. This reduces delays when cleaning up or managing files in databases with large volumes of accounting and inventory records.
Original PR description
## The problem Deleting attachments checks foreign key triggers. Lookups in `account_move` and `stock_picking` tables for `ir_attachment` related fields coming from `l10n_cl_edi` overrides were slow due to missing indexes. ## The solution Added needed indexes to optimize triggers' lookups. ## Benchmark Time benchmark (deleting attachments from a customer database with 224K account moves and 204K stock pickings): |# of rows|Time (Before)|Time (After)| |----------|--------------|-------------| 100 | 29s | 16ms 1000 | 285s | 300ms OPW-6331845
The Azerbaijani Manat (AZN) now uses its official currency symbol, ₼, instead of the previous symbol. This improves accuracy and consistency in currency display for users who work with Azerbaijani currency.
Original PR description
This commit updates the base currency symbol for the Azerbaijani Manat (AZN) to its official Unicode character '₼'. Related Upgrade PR: https://github.com/odoo/upgrade/pull/10107 Backport of: https://github.com/odoo/odoo/pull/262471 task-6112867
Resolved issues and error corrections
This fix preserves the expected behavior of file navigation in the Knowledge app after a Chrome browser change. It prevents newer Chrome versions from accidentally changing how scroll actions are handled, helping users keep a consistent experience.
Original PR description
Since Chrome 150, scrolling methods like `scrollIntoView()` return a Promise instead of `undefined`. This commit adds block braces to ensure the action returns `undefined` and keeps the same behavior as before. Reference: - https://chromestatus.com/feature/5082138340491264 - https://chromium.googlesource.com/chromium/src/+/50f3e3d0a9bc02aad8b8161dbdd59046991dd2c7 runbot-941309
This fix brings improvements from a newer version into Odoo 17 to make the scheduled update of Mexican invoices' SAT status more reliable. Businesses using Mexican e-invoicing should see fewer incorrect or missed status updates when the automated check runs.
Original PR description
Several fixes were applied in version 18.0 to the scheduled action responsible for updating invoices' SAT status. - a6c3465fb86f7af162c90e1adab7bd1da1a1c20d - 1eec6de32c99396ae40587168193dbc44ebae1e3 - a1b130566f6689a0c3c786a98f75c54234467fcc We propose to backport them in version 17.0.
The Peru Profit and Loss report now includes Other Operating Income when calculating gross profit and related totals. This ensures reported profit figures reflect all relevant operating income, improving accuracy for financial review and compliance.
Original PR description
**Steps to reproduce:** 1. Install `l10n_pe` and switching to the Peru company. 2. Create and post a journal entry with a line on account 7520000 (Other Operating Income). 3. Open the Profit and Loss report (PE). 4. The amount appears correctly under "Other operating income" (`PE_PNL_A_5`). 5. "Gross profit", "Operating profit" , "Result before taxes" and "Net Profit" do not change when this amount is added or removed. **Issue:** The "Other operating income" line is excluded from the Gross Profit calculation, and consequently from Operating Profit and every downstream total in the PE Profit and Loss report. **Why this happens:** Gross Profit (`PE_PNL_A_4`) balance expression uses the aggregation with formula `PE_PNL_A.balance - PE_PNL_A_3.balance`, which doesn't include `PE_PNL_A_5.balance` as a term opw-6283907
This fix makes Microsoft calendar connections renew correctly by saving the new refresh token each time access is refreshed. As a result, users are less likely to be asked to log in again every 90 days when their original token expires.
Original PR description
Microsoft issues a new refresh token on every access token refresh (rolling 90-day sliding window). The previous code discarded it, causing users to be forced to re-authenticate every 90 days once the original token expired. Closes #253543
When records are grouped by hour, the labels now use a 24-hour format instead of a 12-hour format without AM/PM. This removes ambiguity in grouped lists and ensures users can clearly distinguish afternoon and evening records.
Original PR description
Description of the issue/feature this PR addresses: When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`. In Babel/LDML formatting, `hh` represents…
Description of the issue/feature this PR addresses:
When grouping datetime fields by hour, `read_group` formats the group display label using `hh:00 dd MMM`.
In Babel/LDML formatting, `hh` represents a 12-hour clock. Since the format does not include an AM/PM marker, afternoon/evening hours are displayed ambiguously in grouped views.
Current behavior before PR:
A datetime value in the afternoon is grouped under a 12-hour label without AM/PM.
For example, records around `13:50` are displayed under:
01:00 20 Mar
Similarly, a datetime value around `16:20` may be grouped under:
04:00 26 Mar
This is ambiguous because the group header does not indicate whether the hour is AM or PM.
Example screenshot showing records around 13:xx grouped under `01:00`:
<img width="251" height="195" alt="image" src="https://github.com/user-attachments/assets/9c394063-f679-4faa-a045-2456cc452fb9" />
Desired behavior after PR is merged:
Hour-based datetime group labels should be unambiguous.
The hour grouping format now uses `HH:00 dd MMM`, so grouped datetime labels render using a 24-hour clock.
For example:
13:00 20 Mar
16:00 26 Mar
This fixes the datetime hour grouping label shown in grouped list views and other `read_group` consumers.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis change avoids a rare timing issue where the same online payment could be processed twice if both the scheduled background job and the customer’s return flow tried to handle it at the same time. It helps ensure each successful payment is finalized only once, reducing the risk of duplicate post-processing and related accounting or order handling issues.
Original PR description
The following use case has been observed: 0. Customer start a payment from /shop/payment. 1. We received the webhook that notifies that the payment succeeded. 2. The payment post-processing cron…
The following use case has been observed: 0. Customer start a payment from /shop/payment. 1. We received the webhook that notifies that the payment succeeded. 2. The payment post-processing cron start (it gather all the transactions that need to be processed, including the customer new transaction) 3. Meanwhile, the customer is redirected back by the payment provider to Odoo, which then redirect to /payment/status and start the payment post-processing for that specific transaction 4. The customer initiated payment processing finishes, he is redirected back to /my/orders/... page. 5. The payment post-processing cron finally start processing the same customer transaction and process it (a second time). In that case, as the transactions to be post-processed backlog was quite high, there is consequent time between the time we gather all the TXs to post-process and actually process the customer transaction. Also we don't end up with a `SerializationError` as the cron do commit after each transaction post-processing. This commit force invalidate individual transaction cache values and recheck if it effectively still need to be post-processed before doing it. opw-6332192 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a connection issue in the Spanish e-invoicing flow when a company uses a seal certificate instead of a personal one. The system now selects the correct AEAT endpoint based on the certificate type, which helps prevent authentication failures and improves reliability.
Original PR description
The AEAT provides different endpoints depending on the type of digital certificate you use. A personal certificate or a seal certificate. The module used always the standard endpoint regardless of the certificate type. Causing authentication failures when a sello certificate was configured. This fix detects the certificate type by checking for the presence of a GIVEN_NAME attribute. task-6169935 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change prevents invoices from showing amounts like “-0.00” when totals are effectively zero after rounding. It improves the appearance and clarity of PDF invoices so customers see a clean zero instead of a confusing negative value.
Original PR description
### Steps to Reproduce 1. Create SO with one line. Unit price $100 + 15% tax 2. Create a down payment for $100 and confirm 3. Create a down payment for the remaining $15 and confirm 4. Create an…
### Steps to Reproduce 1. Create SO with one line. Unit price $100 + 15% tax 2. Create a down payment for $100 and confirm 3. Create a down payment for the remaining $15 and confirm 4. Create an invoice for the original SO, the total is 0.00 5. Download the PDF and notice that the total is -0.00 ### Description of the issue/feature this PR addresses: **Issue:** There should not be a negative sign on the invoice PDF. Because of rounding to accommodate the limitations of binary memory, there is a negligible negative remainder sometimes, which gets shown as -0.00. **Solution:** Update the _compute_tax_totals method to check if the calculated totals and subtotals evaluate to zero using the currency's precision (is_zero()). If a value evaluates to zero, we explicitly force the amount to 0.0 and reformat it using formatLang, ensuring the PDF displays a clean 0.00 ### Current behavior before PR: Some cases cause there to be a negative zero on the invoice PDF. ### Desired behavior after PR: No negative zeroes on the invoice PDF. opw-6298712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change fixes an issue where messages in a conversation could fail to appear after a reload. It improves reliability so users can consistently see the latest thread messages without the screen getting stuck in a blank state.
Original PR description
The Thread component mirrors `thread.isLoaded` into the `state.mountedAndLoaded` flag that gates, in the template, whether the real messages are rendered. That mirroring effect both read…
The Thread component mirrors `thread.isLoaded` into the `state.mountedAndLoaded` flag that gates, in the template, whether the real messages are rendered. That mirroring effect both read `mountedAndLoaded` as one of its dependencies and wrote it. `useEffect` records its dependency array before running the body, so right after the effect sets `mountedAndLoaded` to true the recorded dependencies still hold the pre-write `[isLoaded=true, mountedAndLoaded=false]` pair; that update only settles on a later, microtask-deferred patch. When a second reload runs `reset()` in that window it drives `mountedAndLoaded` back to false while `isLoaded` stays true, and the settling patch then computes the very `[true, false]` pair already recorded. The effect never re-runs, so `mountedAndLoaded` is stranded at false and no message is rendered. Depend on a monotonic `resetCount` instead. Reading it in the effect dependency array subscribes the render to it (OWL subscribes a `useState` proxy's render callback on every read, wherever it happens), so a `reset()` bump re-renders and re-runs the mirror to re-sync `mountedAndLoaded` with `isLoaded`. Bump it only when `isLoaded`: while loading, `applyScroll` resets on every patch, so an unconditional bump would spin the render loop; the guard re-arms only in the case that heals. `reset()` still clears `mountedAndLoaded` (the false dip is needed for the reload scroll handshake), so behaviour is otherwise unchanged. The race is not deterministically reproducible with this version's test tooling, which cannot advance the render loop a single frame, so no test is added here; the fix is covered by tests on later versions. https://runbot.odoo.com/odoo/error/940032