Daily updates from Odoo
Monday, June 22, 2026
15 changes · 17.0
Resolved issues and error corrections
This update ensures GIF functionality in Odoo continues to work smoothly. The previous Tenor GIF API key is being replaced with a Klipy GIF API key due to the Tenor API's planned shutdown on June 30, 2026. Users will need to update their API key settings to ensure GIF sharing remains operational.
Original PR description
Tenor API will be terminated on June 30, 2026: https://developers.google.com/tenor/guides/quickstart This commit makes the Tenor API key input settings use a Klipy GIF API key instead of a Tenor GIF API key. To keep GIF working after this commit, the API key must necessarily be changed to a Klipy GIF API key, as the old Tenor API key would be considered as an invalid Klipy API key. Task-5491965 Upgrade: https://github.com/odoo/upgrade/pull/10516
This update resolves an issue in the 17.0 version of Odoo where users couldn't delete soda mapping records, leading to data management problems. The fix allows users to unlink these records, providing the necessary flexibility to correct errors and maintain accurate accounting data. This improves usability and prevents data blockage.
Original PR description
**PROBLEM** It's impossible to delete soda mapping in 17.0. So if you mess the mapping, you can't do anything about it. **STEP TO REPRODUCE** 1. Install l10n_be_codabox. 2. Select the belgium company, and goes to configurations/accounting. 3. Click on open soda mapping, create a new mapping line. 4. There is no way to delete it. opw-6293829
This update resolves an issue where E-Way Bill amounts were incorrectly calculated when sales prices included tax. The fix ensures that tax-included prices are properly processed, preventing double tax calculations and ensuring accurate E-Way Bill generation. This impacts sales orders with 'Tax Included' settings.
Original PR description
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create…
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create a Sales Order (e.g. unit price 300, qty 600, 18% GST) and confirm the Delivery Challan/Delivery Order. * Generate an E-Way Bill from the Delivery Challan. **Observed behavior:** * The Taxable Amount and Total Invoice Amount are displayed incorrectly in the generated E-Way Bill, including both the printed document and the JSON. * The `ewaybill_price_unit` shows the tax-excluded price (e.g. 254.24) instead of the original tax-included price (300), leading to a double tax exclusion when `compute_all` processes it. **Cause:** * `_l10n_in_get_product_price_unit` in both `l10n_in_sale_stock` and `l10n_in_purchase_stock` unconditionally used `price_subtotal / qty` to compute the E-Way Bill price unit. `price_subtotal` is always tax-excluded, so for tax-included prices, the tax was already stripped. * `_l10n_in_tax_details_by_stock_move` then passed this already tax-excluded price to `compute_all` with taxes that have `price_include=True`, causing `compute_all` to strip the tax a second time (e.g. 254.24 / 1.18 = 215.46 instead of the correct 254.24). **Fix:** * Check whether any of the line's taxes have `price_include` set. If so, use `price_total / qty` (which preserves the tax-included price) so that `compute_all` can correctly extract the tax. Otherwise, continue using `price_subtotal / qty` as before. opw-6273101
This update fixes an issue where the Luxembourg eCDF XML export incorrectly reported financial year data. The change removes a problematic account mapping, ensuring the exported data aligns with the Odoo Profit and Loss view. This improves data accuracy for Luxembourg tax reporting.
Original PR description
Issue: Users reported that the financial year result in the XML export for the Luxembourg eCDF platform is incorrect, despite being correct in the Odoo Profit and Loss visualization. The exported XML populated incorrect amounts in cell 0161 under certain circumstances (namely, in the case of an explicit entry from account 999999 to account 142000). Solution: * Removed account 142 entirely from both the `ACCOUNTS_2019` and `ACCOUNTS_2020` dictionaries so it no longer auto-populates cells 0161/0162 (up to 2019 included) and 2955/2956 (from 2020 onward). * Removed the 2019 threshold condition in the loop bypass for account 142. * Removed the hard-coded manual pop for cell 2955 since it has been removed from the mapping. * Deleted the redundant reassignment of `net142` in the loss calculation block. Ticket [link](https://www.odoo.com/odoo/project.task/6059571) opw-6059571
This update enables branch companies to register on the PEPPOL network as 'sender only' participants, mirroring their parent company's registration. This simplifies the registration process for branch offices and ensures compliance with PEPPOL requirements, streamlining international trade operations.
Original PR description
This task backports the ability to register branch companies as sender only using the same identifier as their parent company task-id-6069374
This update resolves a crash that occurred when users attempted to view Instagram videos within Odoo. The fix now displays the video link instead of the image, ensuring a stable preview experience. This improves user engagement and prevents disruptions when accessing Instagram content.
Original PR description
Purpose ======= When we have a real on Instagram, we try to show the video as an image. When clicking on the broken image, the previewer crash. To fix that issue, we know show the link of the video in the message. Task-5491124 Forward-Port-Of: odoo/enterprise#113487
This update resolves an issue where a duplicate stock move was being created in backorders after a quality check failure. The fix prevents the creation of an unnecessary move when a quality issue redirects a transfer, ensuring backorders are accurately reflected and avoids redundant inventory management.
Original PR description
Steps to reproduce: ------------------- - Install `purchase`, and `quality_control` - Enable Multi-Step Routes in Inventory settings - Create a storable product tracked by lot - Create a Quality…
Steps to reproduce:
-------------------
- Install `purchase`, and `quality_control`
- Enable Multi-Step Routes in Inventory settings
- Create a storable product tracked by lot
- Create a Quality Point:
- Operation Type: Internal Transfer
- Control Per: Quantity
- Configure a failure location
- Enable the 3-Step Incoming route for the warehouse
- Duplicate the Internal Transfer operation type and name it `Internal Transfer 2` Configure the operation types:
- Internal Transfer: <-- this is original one
- Source Location: WH/Input
- Destination Location: WH/Quality Control
- Internal Transfer 2:
- Source Location: WH/Quality Control
- Destination Location: WH/Stock
- Open the warehouse's 3-Step Incoming route
- Locate the push/pull rule whose source location is `WH/Quality Control`
- open that and Change its operation type from internal transfer -> `Internal Transfer 2`
- Create and confirm a Purchase Order for 20 units of the product
- Open the generated receipt
- Validate 12 units using Lot-1 and create a backorder
- Open the Internal Transfer (where source is that PO and there operation type
is internal transfer that original one)
- Demand: 20
- Reserved Quantity: 12
- Click into detail button on stock move and split the move line into:
- 9 units from Lot-1
- 3 units from Lot-1
- save
- Open the Quality Check
- Pass 9 units
- Fail 3 units
- Validate the transfer and create a backorder
- Open the internal transfer whose operation type `Internal Transfer 2`
Issue:
------
`Internal Transfer 2` contains two stock moves:
- Move 1:
- Demand: 20
- Quantity: 9
- This is correct.
- Move 2:
- Demand: 8
- Quantity: 0
- This move should not exist.
Expected behavior:
------------------
`Internal Transfer 2` should contain only the move corresponding to the successfully passed quantity:
- Demand: 20
- Quantity: 9
No additional move with demand 8 and quantity 0 should be generated.
Cause:
--------------------------
A 3-step route pre-creates the whole chain at confirm time: Receipt -> Internal Transfer -> Internal Transfer 2, each linked through move_dest_ids/move_orig_ids. Both fields are the two sides of a single many2many relation (stock_move_move_rel), so removing the relation from either side drops it entirely.
When the user confirms the failure on the quality check, the wizard calls quality.check._move_line_to_failure_location() (quality.py). Because the failure location differs from the next operation's source location, it runs
https://github.com/odoo/enterprise/blob/3a5e30f0bb7c1660827fd209cd74ef3bcd538213/quality_control/models/quality.py#L386
and `_break_mto_link()` then does unlink of `orig_location_id`
```py
self.move_orig_ids = [Command.unlink(parent_move.id)]
self.procure_method = 'make_to_stock'
```
**This is intentional** : it switches Internal Transfer 2 to `make_to_stock` so its `_action_assign()` reserves only what is physically present at Quality Control, instead of chain-reserving the 3 failed units that were rerouted to the failure location.
The side effect is that, because the relation is shared, unlinking parent_move from Internal Transfer 2's move_orig_ids also empties the Internal Transfer move's move_dest_ids.
- when the picking is validated and the backorder is created
When the picking is later validated, `_action_done()` splits off the remaining, never- reserved demand into a backorder move via `_split()` -> `_prepare_move_split_vals()`,
which copies `move_dest_ids` from the original move. but that's already empty,
because of the break at the time of failed quality check.
So the backorder is created with no `move_dest_ids` even though its 8 units have nothing to do with the quality failure they simply haven't
been reserved/processed yet.
https://github.com/odoo/odoo/blob/6feedc18b7873bfde62047ece1a5de882319bc21/addons/stock/models/stock_move.py#L1955
Then action_done trigger ` _action_confirm()` it calls `_push_apply()`.
https://github.com/odoo/odoo/blob/6feedc18b7873bfde62047ece1a5de882319bc21/addons/stock/models/stock_move.py#L966-L967
` _push_apply()` only skips a move if it already has `move_dest_ids` since the backorder has none, it doesn't skip — it searches for an applicable push rule from WH/Quality Control, finds the very same rule that already produced Internal Transfer 2
the first time, and creates a brand new Internal Transfer 2 move for its own demand (8)
via `rule._run_push()`. That new move has quantity 0,
Fix:
--------------------------
Before pushing a move that has no destination, `_push_apply()` now first checks whether a failed, diverted quality check (same product, same upstream chain via move_orig_ids) already exists for it. If so, this move is just a leftover backorder of a transfer that already had its link broken for quality reasons, and the existing destination move already covers it — so the push is skipped instead of creating a duplicate.
Nothing about the quality check wizard or the existing link-breaking
logic was changed; this only stops that breakage from leaking into a later, unrelated backorder.
----
opw-6298637This update resolves a bug that previously prevented the system from correctly calculating bill addresses when address fields were empty. The fix now sets empty address fields to empty strings, ensuring accurate billing information is processed. This improves the reliability of payment authorization transactions.
Original PR description
Fix bug introduced by commit https://github.com/odoo/odoo/pull/267592/changes/c4556637e8eeef07ce6e3cc3b3b4cf28fa10e468 that caused an error if an address field was not set, due to trying to cut a False field. Now, unset fields are set to empty strings. Forward-Port-Of: odoo/odoo#270295
This update corrects a technical issue where the average product review star rating was incorrectly displayed as an H1 element. The change now uses a more appropriate span tag with styling, ensuring better website accessibility and a cleaner design. This improves the overall user experience on product pages.
Original PR description
Problem: The average number of stars in the review on product pages is shown as an h1. This is not sementically valid. Solution: Use a span and apply an h1-like style. Task-6185328 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update ensures Odoo generates PDF invoices that fully comply with ZUGFeRD standards, a crucial requirement for electronic invoice processing. Specifically, it adds a necessary tag to the PDF file to accurately link the visual invoice with its underlying XML data, addressing a technical specification update. This ensures proper integration with Factur-X and supports future ZUGFeRD versions.
Original PR description
Adapt `add_attachment` to allow setting the "AFRelationship" tag on the PDF filespec object, In compliance with Factur-X/ZUGFeRD specs that require the AFRelationship tag in the PDF filespec object to reflect the relationship between the embedded XML and the visual PDF content: - /Data: the visual PDF contains more invoicing data than the XML. - /Alternative: the XML and the PDF are two equivalent representations of the same invoice. Additionally, update the embedded XML filename from `zugferd-invoice.xml` to `factur-x.xml`. The former is marked as deprecated since ZUGFeRD 2.0 Ref: sections 6.2.2, 6.3.1, 6.3.2 of the ZUGFeRD 2.4 specification: https://www.ferd-net.de/en/downloads/publications/details/zugferd-24-english opw-6252082
This update resolves an issue where Odoo Server would unexpectedly crash (exit code 130) during automatic reloads. The fix prevents a race condition triggered by `SIGHUP` signals, ensuring Odoo Server remains stable and reliable even with frequent updates or file changes. This improves the overall stability and uptime of the Odoo instance.
Original PR description
### Summary When `dev_mode` includes `reload`, the `ThreadedServer` FSWatcher triggers a phoenix restart by sending the process a `SIGHUP`, and `signal_handler` turns `SIGHUP` into…
### Summary When `dev_mode` includes `reload`, the `ThreadedServer` FSWatcher triggers a phoenix restart by sending the process a `SIGHUP`, and `signal_handler` turns `SIGHUP` into `KeyboardInterrupt`. `ThreadedServer.run()` only catches that in its wait-loop — but there are two windows where the `KeyboardInterrupt` is raised **outside** the `try/except`, escapes `run()`/`main()`, and exits the interpreter with code **130**. Under Docker's default `restart: no`, PID 1 dies and the container does not come back. 1. **Startup** — a `SIGHUP` during `self.start() + preload_registries()` (e.g. a save while a previous reload is still loading modules). 2. **Teardown / duplicate** — a single save often emits two FS events; the FSWatcher's `if not odoo.phoenix:` dedup races across threads and fires two `SIGHUP`s. The first begins the phoenix teardown; the second lands during `self.stop()` / `_reexec()`, outside the guarded region, and escapes the same way. ### Reproducer (deterministic) Boot a threaded server and signal it a few times in quick succession: ```bash odoo-bin -d <db> --workers 0 # ThreadedServer # once it is up, with <pid> = the odoo process: for i in $(seq 8); do kill -HUP <pid>; sleep 0.12; done ``` Unpatched the process exits **130**; patched it survives after a single clean phoenix reload. The same happens from a single editor save (duplicate FS events) or a bulk file change. ### Fix Two guards in `signal_handler`, plus bracketing the startup window in `run()`: - **Startup**: a module flag marks the `self.start() + preload_registries()` window; a `SIGHUP` arriving then is *deferred* (recorded, not raised). After the window `run()` replays its effect inline so the wait-loop performs the normal phoenix restart. - **Duplicate**: if `odoo.phoenix` is already set a restart is already in flight, so a further `SIGHUP` is redundant and is ignored rather than raised. `SIGINT`/`SIGTERM` are untouched — `Ctrl-C` and `docker stop` keep working unchanged. The fast path (no `SIGHUP`) is one flag set + one clear per startup. ### Notes - Targeted at **17.0** (oldest affected branch) for forward-porting. The 17.0 → 18.0 hop will conflict: on 18.0/master the flag is the module-level `server_phoenix` global and `run()` wraps the critical section in `with Registry._lock:`. I'll resolve the forward-port. - Prior art: #21209 (introduced the phoenix flag), #206898 (graceful reload), #207930. - CLA: signed via #269075 (Codeforward corporate CLA).
This update resolves a test failure related to database constraint violations (specifically `RESTRICT_VIOLATION`) when using PostgreSQL 18. The change involves updating a test to handle errors more generically, ensuring the email alias functionality continues to work correctly. This is a routine maintenance fix.
Original PR description
This commit is kind of a follow up of
odoo/odoo@39cd4ea856fe00f5674f8c44b2b66cbf2705426d (in 18.0).
In a nutshell, following a standard-compliance fix (postgres/postgres@086c84b) has led to `RESTRICT_VIOLATION` being emitted in cases which formerly emitted `FOREIGN_KEY_VIOLATION`. One such case is specifically being tested for by `test_alias_domain_setup`, leading to this test failing systematically when running pg18:
psycopg2.errors.RestrictViolation: update or delete on table "mail_alias_domain" violates RESTRICT setting of foreign key constraint "mail_alias_alias_domain_id_fkey" on table "mail_alias"
DETAIL: Key (id)=(191) is referenced from table "mail_alias".
This commit updates the test to use the more generic `IntegrityError` as it's probably more than sufficient for our purposes.This update fixes an error in the German (skr03) accounting template. The incorrect account codes for cash discounts have been replaced with the correct ones, ensuring accurate financial reporting for German businesses using Odoo. This ensures compliance with German tax regulations.
Original PR description
The default cash discout accounts referenced in the
German skr03 template used the wrong account codes.
The template has been updated with the right ones.
task-4915939
opw-4909059
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update fixes an error in the German (skr03) template for financial reports. The incorrect account codes for cash discounts have been corrected, ensuring accurate reporting for German businesses using this template. This ensures compliance and reliable financial data.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059
This update corrects a missing valid NUIT number in the MZ demo company setup. The change ensures the demo company accurately reflects MZ tax regulations, preventing potential errors during testing and demonstration. This fix resolves a Runbot error related to data validation.
Original PR description
Newer versions of stdnum (2.2) also test the number for MZ We did not have a valid NUIT number in the MZ demo company. Runbot error: https://runbot.odoo.com/runbot/build/114118067 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