Monday, August 24, 2026
46 changes · master
Resolved issues and error corrections
Cancelling the product configurator in Point of Sale no longer shows optional products for an item that was not added. This prevents cashiers from being prompted to add extras for a discarded product, reducing confusion during checkout.
Original PR description
When discarding the product configurator, we still showed the optional product. We no longer do that as no one wants to add optional products to a not-added product. task-6442422 Forward-Port-Of: odoo/odoo#283378 Forward-Port-Of: odoo/odoo#282916
Fixes issues in Odoo's JSON logging so ignored fields and test-related log information are handled correctly. Adds automated checks to help prevent these logging problems from returning, improving reliability for monitoring and troubleshooting.
Original PR description
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also…
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatter(ignore_record_keys=[])` The purpose was to be able to easily include all keys and ignore the default ingnore list, but this makes the additional blacklisting of a few keys more tedious, and the general usage and implementation more complex `JSONFormatter(ignore_record_keys=[*JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS, 'other key'])` To simplify the logic, **this is not the case anymore**, so to include all keys something like this would be needed `JSONFormatter(additional_record_keys=JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS)` Or an hardcoded list. Forward-Port-Of: odoo/odoo#284051 Forward-Port-Of: odoo/odoo#279049
This fix prevents the timesheet assistant from accidentally changing event data and resolves errors that could appear when removing or viewing certain timesheets. Users should experience fewer interruptions and more dependable timesheet handling.
Original PR description
## [FIX] timesheet_grid: avoid altering consumedEvents Before this commit, the objects inside consumedEvents attribute are altered because we keep the reference of those objects. This commit avoid altering the consumed events. ## [FIX] timesheet_grid: use recordsByStart instead of records Forward-Port-Of: odoo/enterprise#128036 Forward-Port-Of: odoo/enterprise#127698
This fix prevents planning shifts from failing when no related sales order line is attached. It ensures the customer field is still set safely, improving reliability for sales planning workflows.
Original PR description
Before this commit, when the shift has no SOL set, the `_compute_partner_id` crashes because the value for partner_id field is not set for that shift. This commit fixes the compute method of partner_id to make sure the value is correctly set for all shifts. Forward-Port-Of: odoo/enterprise#128965
This fixes an internal test for appointment rescheduling so it behaves consistently when demo data is present. It helps prevent false test failures without changing the customer-facing appointment experience.
Original PR description
In test_reschedule_appointment_event the tracking is rendered by the public user, which has no timezone hence fallback to UTC. But the expected values are formatted by the test environment, running as OdooBot, whose timezone demo data sets to Europe/Brussels. Without demo data both fall back to UTC and the test passes. Format the expected values in UTC as well. Runbot-946307
Timesheet suggestions now handle away-from-keyboard periods more reliably, so breaks and inactive time are less likely to be missed or overwritten. This helps employees and managers get a more accurate view of working time when using ActivityWatch-based timesheet assistance.
Original PR description
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was…
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was not “always active.” This caused AFK events to be incorrectly overridden. 2. During event normalization, certain events were lost entirely, resulting in important events not being counted. 3. When merging two event timelines, zero‑duration gaps were treated as valid, preventing proper merging of surrounding events. 4. ActivityWatch sometimes produced empty gaps instead of AFK events, causing breaks to go unrecorded. ## New Expected Behavior After this Commit 1. Events now follow the updated priority system: a. Always‑active key events b. Always‑active non‑key events c. Non‑key AFK events d. Other key events e. Other non‑key events 2. Events are now shortened or split so that the latest event always has priority, while minimizing unnecessary event removal. 3. Zero‑duration gaps are skipped when merging event lists. 4. Any gap larger than 3 minutes, between the first and last event and containing no events is automatically filled with an AFK event. ## Additional Notes Because point 4 introduces additional AFK events, several tests were updated to reflect the new behavior. task-[6455412](https://www.odoo.com/odoo/project/4105/tasks/6455412) Forward-Port-Of: odoo/enterprise#128039 Forward-Port-Of: odoo/enterprise#127811
Inventory move lines now keep the transfer's original scheduled date after validation instead of switching to the processing date. This makes Moves History filtering, grouping, and sorting by Scheduled Date match the date shown on the transfer, improving reporting accuracy.
Original PR description
### Problem `stock.move.line.scheduled_date` is related to `move_id.date`, and `stock.move.date` only holds the scheduled date **until the move is done** — at validation it is overwritten with the…
### Problem `stock.move.line.scheduled_date` is related to `move_id.date`, and `stock.move.date` only holds the scheduled date **until the move is done** — at validation it is overwritten with the processing date, as its own help states. So on a done move line the field returns the effective date under a "Scheduled Date" label. It shows up in Moves History (Inventory > Reporting), which lists done lines by default: filtering, grouping or sorting by "Scheduled Date" silently uses the effective date, and it contradicts the "Scheduled Date" displayed on the transfer, which does survive the validation (`stock.picking._compute_scheduled_date` ignores done moves). **Steps to reproduce** 1. Create a receipt scheduled tomorrow and validate it today. 2. Inventory > Reporting > Moves History, group by "Scheduled Date". 3. The line falls under today instead of tomorrow, while the transfer form still shows tomorrow. ### Fix Follow `picking_id.scheduled_date`, which keeps the scheduled date once the transfer is done. The field is only displayed in `stock.view_move_line_tree_detailed`, and every action using that view (`stock.action_get_picking_type_operations`, the Prepare Wave actions and the Add to Wave wizard) already restricts the lines to those belonging to a transfer, so no view loses a value it used to show. I hereby agree to the terms of the CLA available at: https://www.odoo.com/cla
Users who manually replenish stock will now see the expected notification when a purchase order is created. This makes the replenishment process clearer and helps teams confirm that their order action was successful without having to search for the purchase order manually.
Original PR description
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track…
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track Inventory` - Purchase > Add a Vendor `Ice cream man` - Reordering rules > Create a new reordering rule and save: - Trigger: Manual - Min: 5 - Max:10 - Press the `Order` button ## Observed Behavior: No notification is displayed about the newly created purchase order. ## Root cause: When the Order button is pressed, the `action_replenish` method is called. This method invokes `_procure_orderpoint_confirm` at [1]. The `_procure_orderpoint_confirm` function is responsible for creating procurements from orderpoints. During this process, it retrieves the procurement values using `_prepare_procurement_values` that are later used at [2]. However, `_prepare_procurement_values` only includes the orderpoint in the procurement values when the orderpoint's trigger is set to automatic, and not when it is manual, as shown at [3]. These procurement values are then used by `_run_buy` to create a purchase order and purchase order line at [4]. Since the orderpoint is not linked to the purchase order line in this case, no matching order is found at [5], which leads to the reported issue. **Which commit caused this unintentional behavior?** This behavior was unintentionally introduced by this [commit](https://github.com/odoo/odoo/commit/2a0d2c64d0027f540101447289b4c1a10cb3ecdf) . That commit fixed an issue where purchase order lines were not being merged for temporary manual orderpoints that are created dynamically based on product demand. [1]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L342-L349 [2]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L737-L741 [3]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L687-L701 [4]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock_rule.py#L156-L165 [5]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock.py#L276-L296 [6]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L365 [7]- https://github.com/odoo/odoo/blob/6a84d3e519892be333552e2e0ebf8da87e0a760c/addons/purchase_stock/models/purchase_order_line.py#L380-L384 ## Solution: Instead of removing the orderpoint ID from the procurement values, we reuse the same conditions used to identify temporary orderpoints for cleanup at [6]. Based on this, we determine how purchase order lines should be merged in the `_run_buy` method. With the previous implementation, no orderpoint was included in the procurement values. As a result, the condition at [7] checking for orderpoints always evaluated to True, causing the system to identify an existing purchase order line for the same product as a merge candidate. This solution allows us to retain that fix as well as avoid the error of notifications not showing up. opw-6311520 Forward-Port-Of: odoo/odoo#283853 Forward-Port-Of: odoo/odoo#271993
Argentine delivery operations using class X document types can now be saved without entering CAI authorization details or an expiration date. This aligns the workflow with local regulations, where those fields are only required for class R delivery notes.
Original PR description
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to…
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to produce: - Install `l10n_ar_stock` with demo data - Switch Company to `(AR) Exento` - Create a warehouse - Configuration > Operation Types > Delivery Orders - Set Document Type to `'(94) MAILING X' `and try to save ## Observed Behavior: The fields 'CAI' and 'CAI Expiration Date', which represent the authorization code and expiration date issued by the government, are currently configured as required fields. **Expected Behavior:** As specified on the [government site](https://www.argentina.gob.ar/normativa/nacional/resoluci%C3%B3n-1415-2003-81316/actualizacion#:~:text=Los%20datos%20indicados%20en%20el%20inciso%20a%29%2C%20puntos%207%2C%2010%2C%2011%2C%2012%20y%2013%2C%20s%C3%B3lo%20ser%C3%A1n%20para%20los%20remitos%20clase%20%27R%27%2E): > > 12. Printing authorization code, preceded by the acronym 'CAI No. ...'. > 13. Expiration date of the receipt, preceded by the legend 'Expiration Date ...' > > 'The data indicated in section a), points 7, 10, 11, 12 and 13, will only be for 'R' class delivery notes.' These statements indicate that the information mentioned in points 12 and 13, including the **CAI** and **CAI Expiration Date** fields, is applicable only to **'R'** class delivery notes. Therefore, for class X delivery notes, these fields should be optional rather than required. ## Root Cause: According to [1], the field is configured as a required field when a Document Type ID is selected. This configuration causes the **CAI** and **CAI Expiration Date** fields to become mandatory, regardless of the document type requirements defined by the government specification. [1]- https://github.com/odoo/odoo/blob/62b05c4ea61942072b6b1fb420fe3efedb11ed14/addons/l10n_ar_stock/views/stock_picking_type_views.xml#L11-L16 ## Solution: Apply constraints that align with the government specifications, allowing the CAI and CAI Expiration Date fields to remain optional for document types where they are not required. opw-6359503 Forward-Port-Of: odoo/odoo#283822 Forward-Port-Of: odoo/odoo#275533
Incoming Peppol vendor bills are now checked against previously imported bills before they are processed. This prevents duplicate bills from being created and marks repeated messages as handled so they do not reappear later.
Original PR description
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282349 Forward-Port-Of: odoo/odoo#274963
Fixes an error that occurred when users clicked the Recorded button on field service interventions. Users can now reliably view the timesheets logged for an intervention without needing an extra project planning integration installed.
Original PR description
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field…
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field service billing feature (Planning > Configuration > Settings > Field Service > "Invoice your time and materials to your customers") without installing Project's planning integration 2. Set the project in Planning > Configuration > Settings > Field Service 3. Create an intervention and assign a resource to it 4. Click the "Recorded" smart button **Current behavior:** 'super' object has no attribute 'action_open_timesheets' **Expected behavior:** The timesheets logged on the intervention are listed. **Cause of the issue:** `action_open_timesheets` on `planning.slot` is defined in two modules only: `project_timesheet_forecast` provides the base implementation, and `planning_field_service_sale_timesheet` extends it through `super()`. Since `59a04091c403` dropped `project_timesheet_forecast_sale` from the dependencies of `planning_field_service_sale_timesheet`, nothing guarantees the base implementation is part of the model's inheritance chain anymore: `project_timesheet_forecast` is auto installed only together with `project_forecast`, which no module of the field service stack depends on. The smart button is rendered by `planning_field_service_sale_timesheet` itself, so it stays visible in such an installation while the `super()` call has nothing to resolve to. **Fix:** That same commit already made the field service module self-sufficient for `_get_timesheetable_project`, `_compute_allow_timesheets` and `_compute_allow_billable`, leaving the project forecast flavour to the `project_timesheet_forecast_field_service_sale` bridge, and `action_open_timesheets` is the only method that was left relying on the other stack. Building the action from the module's own hooks preserves that separation, whereas depending on `project_timesheet_forecast` again would pull Project back into every field service installation, which is precisely what that commit set out to avoid. opw-6391972 Forward-Port-Of: odoo/enterprise#126489
The Belgian salary configurator now calculates wages consistently when employees have extra-legal leave and a mobility budget. This prevents the mobility budget from being incorrectly adjusted for leave, so employer cost and gross wage figures align with the standard payroll formula.
Original PR description
Forward-Port-Of: odoo/enterprise#112723
Adds automated coverage to ensure currency translation adjustments use the correct exchange rates when the company currency changes over time. This helps prevent inaccurate financial report values in fluctuating-rate scenarios.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#125363 Forward-Port-Of: odoo/enterprise#123055
Odoo now correctly detects when an internal stock transfer leaves a replenished source location short of stock. This ensures the Replenishment report creates the needed reordering suggestion, helping businesses avoid missed restocking actions after moving inventory between internal locations.
Original PR description
Steps to reproduce: ------------------- 1. Install `stock` module. 1. Enable the "Storage Locations" from setting. 2. Create an internal location and enable `replenish_location` on it and set…
Steps to reproduce:
-------------------
1. Install `stock` module.
1. Enable the "Storage Locations" from setting.
2. Create an internal location and enable `replenish_location` on it and set warehouse(WH) as Parent.
3. Create a storable product track by quantity with no on-hand quantity.
4. Create an internal transfer from the warehouse stock location to the new internal location.
5. Confirm the transfer.
6. Open the Replenishment report.
Issue:
------
No manual reordering rule is created for the product at the source location, although
the confirmed transfer makes its forecasted quantity negative.
If `replenish_location` is disabled on the destination, the expected reordering rule is created.
Cause:
------
When both the source and destination have `replenish_location=True`, Odoo considers both locations
inside the same replenishment area. Therefore, the internal transfer is not counted as either
incoming or outgoing, and no replenishment is created for the source location.
Code Flow:
Opening the Replenishment report calls
`stock.warehouse.orderpoint.action_open_orderpoints()`, which delegates the report preparation to `_get_orderpoint_action()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L324-L326
`_get_orderpoint_action()` first obtains every location that must be monitored for replenishment through `_get_orderpoint_locations()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L520
`_get_orderpoint_locations()` returns all locations whose `replenish_location` field is enabled:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L799-L800
All these locations are passed together to
`product.product._get_domain_locations_new()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/product.py#L396-L464
This method treats the provided locations and their descendants as a set. Its move domains are equivalent to:
- incoming: destination is inside the set and source is outside;
- outgoing: source is inside the set and destination is outside.
Consider the following sibling locations:
WH
├── Stock
└── Replenish Location
and the transfer:
Stock -- 3 units --> Replenish Location
When `replenish_location` is disabled on the destination, the considered location set contains only `Stock`:
considered location set = {Stock}
The source is inside the set and the destination is outside:
source inside = True
destination outside = True
The transfer therefore matches the outgoing domain:
source inside AND destination outside
True AND True
= True
It is included in `moves_out`, and the preliminary forecast for `Stock` becomes:
0 on hand + 0 incoming - 3 outgoing = -3
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L552
The negative quantity is detected and a manual orderpoint is created.
When `replenish_location` is enabled on the destination, both sibling locations belong to the considered location set:
considered location set = {Stock, Replenish Location}
Both ends of the transfer are now inside:
source inside = True
destination inside = True
destination outside = False
source outside = False
The transfer matches neither aggregate domain:
incoming:
destination inside AND source outside
True AND False
= False
outgoing:
source inside AND destination outside
True AND False
= False
The transfer is considered internal to the considered location set and is therefore absent from both `moves_in` and `moves_out`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L530-L540
This aggregate treatment conflicts with the next step, where `_get_orderpoint_action()` computes the quantity separately for each replenishment location:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L549-L552
When `Stock` is evaluated separately, the internal transfer has already been discarded. Its calculated outgoing quantity is consequently zero:
0 on hand + 0 incoming - 0 outgoing = 0
As the quantity is not negative, the product is not scheduled for the final `virtual_available` computation and no manual orderpoint is created.
Fix:
----
Also retrieve moves whose source and destination are both inside the aggregate replenishment-location set.
Include these internal moves in both the incoming and outgoing grouped queries. The existing per-location path filtering then assigns each side correctly:
- the source replenishment location counts the move as outgoing;
- the destination replenishment location counts it as incoming.
For the reported transfer, this produces:
Stock:
0 on hand + 0 incoming - 3 outgoing = -3
Replenish Location:
0 on hand + 3 incoming - 0 outgoing = 3
This is correct because the report creates replenishment propositions per location, even though the initial move query is performed for all replenishment locations together.
---
opw-6462608
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#282168Sales order sections and subsections no longer show quantity delivered, delivery percentage, or unit price fields that do not apply to them. This keeps order lines easier to read and avoids confusion when reviewing structured sales orders.
Original PR description
On the SO form view, some fields that are not meant to be displayed on sections/subsections are displayed on them. These fields are: qty_delivered, qty_delivered_percent, and price_unit. Follow-up task: 6075605 and 6450100 <img width="1223" height="286" alt="screen" src="https://github.com/user-attachments/assets/f07e2343-c3ba-46b7-b6d3-b4e4d20491a2" />
This fixes a timing issue in the website page creation flow where the interface could remain blocked while redirecting to a newly created page. It makes the automated flow wait until navigation is fully complete, improving reliability of website testing and reducing false failures.
Original PR description
runbot-944311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278652
Belgian payroll demo records now use the correct meal voucher values and Belgian office work locations, making test employee data more accurate. The update also fixes a company mismatch on a demo vehicle to avoid multi-company errors during testing.
Original PR description
In Belgian demo data, several employees have an incorrect meal voucher employee share set to 0.00€ instead of the standard rate. Additionally, the default work address for BE test employees is set to a US location. This updates the demo records: - Sets meal voucher amount to 8.00€ and employee's share to 1.09€ (except for employees in JC 999). - Updates all BE test employees' work location to "Belgian offices". Task-6471822
The accounting app now correctly blocks fiscal year periods that fully contain an existing fiscal year. This helps prevent duplicate or conflicting accounting periods, reducing the risk of reporting and closing errors.
Original PR description
Before this commit: - The current constraint for overlap check allows if we define a new, larger fiscal year that completely swallows an existing smaller one (e.g., creating Aug 2025 - Nov 2026 when Sept 2025 - Oct 2026 already exists). After this commit: - The constrain domain was changed to consider the above missed case.
The tax totals display no longer shows cash rounding controls in sales and purchase documents, where they are not intended to be used. This keeps rounding behavior limited to accounting and invoicing, reducing confusion for users preparing quotes, orders, or purchase documents.
Original PR description
The cash rounding on the tax totals widget is intended to work only with accounting/invoicing, but not sales/purchases.
Customers can now redeem more than one eligible reward from the same loyalty coupon when they have enough points. This removes an incorrect block that prevented combining rewards such as a discount and a free product, improving checkout flexibility and loyalty campaign value.
Original PR description
Steps to produce: --- - Install the `website_sale_loyalty` module. - Navigate to Discount & Loyalty and create a new coupon program. - Keep the existing `10% Discount reward` and add a second reward…
Steps to produce: --- - Install the `website_sale_loyalty` module. - Navigate to Discount & Loyalty and create a new coupon program. - Keep the existing `10% Discount reward` and add a second reward of type `Free Product`. Select a product for the free product reward. - Generate a coupon and set its balance to `2` coupon points. - Open the website and add a product to the shopping cart. - Apply the generated coupon code. - Attempt to redeem both rewards (the 10% discount and the free product reward) using the same coupon. Issue: --- - When trying to apply the second reward, it shows `This program is already applied to this order.` Root cause: --- - Once a program was applied to the order, subsequent rewards from the same program were blocked, regardless of whether the customer had enough points to claim them. Solution: --- - If a reward from an already-applied program is still claimable (i.e, the customer has sufficient points), allow it to be applied to the order. opw-6247206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Employees on flexible schedules without a set average daily hour value will now have full-day leave recorded correctly. This prevents leave requests from being saved as zero-duration, improving accuracy in absence tracking and payroll-related records.
Original PR description
…duration leave When a flexible schedule has no average_hour_per_day set (hours_per_day=0), _get_hours_for_date computed [12-0, 12, 12+0] = (12.0, 12.0), producing a zero-duration leave (date_from == date_to). Treat hours_per_day=0 like a fully flexible employee and return (0, 24) so the leave spans the full day. Task-6488608
Belgian payroll now correctly recognizes a full working day when an employee follows a schedule where some days have fewer contracted hours than others. This prevents payslips from incorrectly showing full days as half-day attendances, improving payroll accuracy for affected work schedules.
Original PR description
Bug: - Create a working sched were one day has less working hours than the rest. - when generating a payslip for an employee linked to that working sched , you'll have half-day attendances even…
Bug: - Create a working sched were one day has less working hours than the rest. - when generating a payslip for an employee linked to that working sched , you'll have half-day attendances even though he worked all his days Reason : - in _get_work_hours_split_half , when building work_data, we compare the duration worked by the employee that day not against the contractual amount of that that but instead we use self.resource_calendar_id.hours_per_day or the max hours per day on that working day , so the day with the least contractual hours on that working sched for exemple will fail this condition " float_compare(duration_sum, number_of_hours_full_day, 2) != -1" even if the employee worked that whole day. Fix: - for fixed scheds : we builed hours_per_dayofweek where we store the hours for each day of the week , later on , we check the weekday and retreive the corresponding official working hours on that day. - for variable scheds: because in this case each day can have its own officil working hours , we fetch the official hours of a certain date right before the logic that determines if it's a full or half a day. task - 6377396 Forward-Port-Of: odoo/enterprise#124100
This fixes an issue where AI assistants could attach request details to the wrong part of a resumed conversation. It prevents confusing or blank replies in Discuss and helps both Google Gemini and OpenAI produce responses based on the right user message.
Original PR description
`_append_context_part` puts the context of the current request on the last entry of the history, whatever that entry happens to be. That is the user's message on a normal turn, but a turn resumed from a `user_input_request` carries the answer back as a tool response, so the context landed on that instead: Google then received a turn mixing a `functionResponse` with a text part, which Gemini answers with a lone newline, posted as the agent's reply and shown in Discuss as a removed message. OpenAI appended it to the output of the tool call instead, making the model read the current context as part of what the tool returned. Both providers now walk back to the last message of the user and attach the context there, leaving tool responses untouched. A normal turn is unchanged, that message being the last entry already.
Shopfloor users can now finish the final work order in continuous production after entering produced quantities. The update also corrects displayed produced quantities when assigning serial numbers, reducing confusion and preventing blocked manufacturing steps.
Original PR description
Previously there was a limitation for continuous production in shopfloor, that blocked the user from marking a workorder as done after registering a quantity. This commit fixes it by assigning the production's `quantity_producing` to the work order's `qty_produced` if it is the final work order. This unblocks the user and allows them to complete the work order. Forward-Port-Of: odoo/enterprise#125787
Manufacturing change orders can now be created successfully from incoming emails sent to configured ECO aliases, even when no product is included in the email. This prevents bounced messages and ensures teams can capture change requests through email as intended.
Original PR description
Steps to reproduce --- 1. In Settings > Technical > Email > Alias Domains, create an alias domain (e.g. `example.com`). 2. Open the ECO Types configuration, pick a type (e.g. "BOM Updates"), and set…
Steps to reproduce --- 1. In Settings > Technical > Email > Alias Domains, create an alias domain (e.g. `example.com`). 2. Open the ECO Types configuration, pick a type (e.g. "BOM Updates"), and set its Email Alias to `bom-updates`. 3. Send an email to `bom-updates@example.com` with any subject and body. 4. The gateway fails to open the change order: the sender receives a bounce and no `mrp.eco` appears under that ECO type. Issue --- `product_tmpl_id` on `mrp.eco` is defined with `required=True`: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L261-L266 That constraint was added by ac635694 ([IMP] mrp_plm: ux improvements), which tightened the form UX but did not account for the mail gateway, which opens change orders without a product. A change order can be created from an incoming email: the alias declared on `mrp.eco.type` routes the message to `mrp.eco`, and `_alias_get_creation_values` injects only `type_id` into the creation values: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L55-L61 The gateway then builds the record with `message_new`, called from `_message_route_process`: https://github.com/odoo/odoo/blob/c6ef99510adcb079f34657aa66dcf191928e3355/addons/mail/models/mail_thread.py#L1553-L1575 https://github.com/odoo/odoo/blob/c6ef99510adcb079f34657aa66dcf191928e3355/addons/mail/models/mail_thread.py#L1402-L1413 An email carries no product, so those creation values have no `product_tmpl_id`. `required=True` is enforced only by the database `NOT NULL` constraint, so on any database where that constraint is present the gateway `create` raises and the incoming request is lost. A product is not actually needed until the change order starts its revision, where `product_tmpl_id` is first read to copy the BoM and gather its documents: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L755-L777 opw-6351438
This fix makes forms with many product lines load and respond much faster by reducing unnecessary page layout recalculations. Large sales orders that previously took many seconds to display should now become usable much more quickly, improving productivity for users handling complex orders.
Original PR description
this is more like an experiment, to see if batching read and dom updates would help. this commit changes loading a SO view from 19.8s to 2.6s, so it looks like it helps 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#282788
This fixes how Indian localization classifies purchase entries for imported goods and services, especially credit and debit notes. It helps keep GST reporting aligned with the correct treatment for reverse charge services and moves invalid import-without-RCM cases out of scope.
Original PR description
Previously:
1.`purchase_cdnur_regular` section was assigned to credit/debit notes of:
- import of goods
- import of services without RCM However:
- import of goods should be handled through bill of supply
- import of services without RCM is not possible Therefore, with this commit, such journal items are moved to `purchase_out_of_scope`.
2.`purchase_imp_services` section included import of services both with and
without RCM. Since import of services without RCM is not possible, those
journal items are now moved to `purchase_out_of_scope`.
3.Credit/debit notes of import of services with RCM were previously moved to
`purchase_out_of_scope`, which was incorrect. With this commit, they are now
correctly moved to `purchase_imp_services`.
task-6330737
Forward-Port-Of: odoo/odoo#276721
Forward-Port-Of: odoo/odoo#272453Odoo now ignores a saved default search filter when its linked record no longer exists. This prevents affected screens from crashing and lets users continue working normally.
Original PR description
…'t exist Have a search view with a m2o field Have an action that sets search_default_m2o: [/BAD ID/] Before this commit there was a crash After this commit, we simply ignore the filter. task-6469841 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#282738
This fixes an issue where pressing Shift+Enter in Safari created a new paragraph instead of a soft line break in the editor. Users editing Knowledge articles on Mac Safari can now format text consistently with other browsers.
Original PR description
**Steps to reproduce:** - Use a Mac with Safari - Install Knowledge app - Go to any article - Press Shift+Enter to try to enter a soft line break - Hard split is done instead **Issue:** Shift+Enter causes a `insertParagraph` event instead of `insertLineBreak` in Safari, which triggers the `SplitPlugin` instead of the `LineBreakPlugin`. **Fix:** Check if the browser is Safari and call `insertLineBreak` from the `SplitPlugin` (when needed) by listening to the "keydown" events. (note: I was not able to find any other key combination to properly trigger the `insertLineBreak` event in Safari) opw-6413507 Forward-Port-Of: odoo/odoo#281458
Restaurant point-of-sale orders now keep combo meal items assigned to the correct course when a combo is split into individual items. Courses are also cleaned up automatically when all related items are removed, helping staff keep orders clearer and reducing kitchen confusion.
Original PR description
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521 Forward-Port-Of: odoo/odoo#283143 Forward-Port-Of: odoo/odoo#260276
This fix prevents certain Indian localization reports from failing when they use shared report handling logic. The B2C HSN line adjustment now only runs for the GSTR-1 report, improving reliability for other reports.
Original PR description
Currently, every l10n_in report is handled by a single handler. Therefore, a check condition is required for each report option. This check was missing in _custom_line_postprocessor, which removes the B2C HSN line conditionally. As a result, it could cause a traceback for reports other than GSTR-1. This PR fixes the issue by adding a condition to ensure that the B2C HSN line is removed only for the GSTR-1 report.
Quotation PDFs with product images now keep long product names and descriptions within their columns. This improves the readability and professionalism of sales quotes, especially when products have lengthy descriptions or unbroken text.
Original PR description
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by…
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by some incompatibility between wkhtmltopdf and d-flex, adding `col` to the product name container forces it to respect column boundaries. This commit also adds `text-break` as having a long uninterupded string in the description would end up stretching the column and making the next ones disapear. <img width="811" height="266" alt="image" src="https://github.com/user-attachments/assets/90043c88-d03f-4324-9935-e669f6a256ab" /> <img width="964" height="431" alt="image" src="https://github.com/user-attachments/assets/2b8e8a6c-6fd5-4813-8160-d94bbb5490d1" /> ### Steps to reproduce: - Enable Display Product Images in the setting - Create a product with an image - Create a quotation with said product and add a description that is long enough to break to the next line - Print said quotation - You will notice that before the line breaks it will overflow to the next column (you might need to tweak the description a bit by removing or adding a few lines) opw-6367076 Forward-Port-Of: odoo/odoo#275978
Indian GST purchase reports now better reflect legal reporting requirements for imported goods and services. Imports of services are no longer shown in GSTR-2B, and GSTR-3B reporting has been adjusted to match the latest section rules.
Original PR description
As per the law, import of services is not required to be shown in GSTR-2B. Therefore, the related report lines are removed in this commit. Additionally, GSTR-3B reporting is now handled according to the updated section changes for import of goods and services. task-6330737 Forward-Port-Of: odoo/enterprise#124550 Forward-Port-Of: odoo/enterprise#121925
WhatsApp messages using templates with many mixed placeholders now send each value to the correct spot. This prevents customers from receiving messages with mismatched details when templates include 10 or more variables.
Original PR description
**Issue**:
Sending a WhatsApp template with 10 or more variables can assign values to the wrong placeholders when the body contains mixed variable types, such as free text, field, or user name variables.
Templates containing only free-text variables are not affected.
**Reason**:
Meta consumes template parameters positionally, but for mixed variable types, Odoo built the parameter list using the template variable recordset order.
That order can differ from the numeric placeholder order, notably placing {{10}}, {{11}}, {{12}}... before {{1}}
when sending the message, as the payload parameters are not ordered by their numeric placeholder index.
**Fix:**
Sort body variables by their numeric placeholder index before preparing the Meta payload.
Task-6401501
Forward-Port-Of: odoo/enterprise#128492
Forward-Port-Of: odoo/enterprise#125671German DATEV exports now handle bank settlements involving three different currencies by splitting them into compliant accounting legs. This prevents export issues and ensures each DATEV line uses only one foreign currency while leaving normal transactions unchanged.
Original PR description
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank…
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank journal is held in another currency (C2), - the company uses a third currency (C3). - The existing export logic could not represent the bank liquidity and foreign AR/AP currencies separately in such cases. Fix: - Detect 3-currency cases from bank statement transactions and their liquidity line. - Use the DATEV clearing account (1360 SKR03 / 1460 SKR04) to split the transaction into two logical legs: - Bank → Clearing (bank journal currency) - AR/AP → Clearing (payer currency) - Emit the liquidity leg only once when multiple foreign AR/AP lines are reconciled against the same bank transaction. - Keep regular 1- and 2-currency transactions on the existing export path. Impact: - Correctly represents 3-currency bank settlements in DATEV. - Keeps each exported line in a single foreign currency. - Leaves manual entries and payment transactions outside this specific handling, as the scenario is specific to the bank liquidity line. taskID-5457547 Forward-Port-Of: odoo/enterprise#128876 Forward-Port-Of: odoo/enterprise#109010
Barcode deliveries now use the real storage location of a scanned serial number when it was not already reserved. This prevents inventory from being deducted from the wrong parent location, keeping stock counts accurate across warehouse sublocations.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial…
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial stored in a sublocation (e.g. WH/Stock/Section 2). 4. Confirm a sale order for it, open the delivery in Barcode, and scan an unreserved serial. Issue --- Scanning the unreserved serial creates a new move line that falls back to _defaultLocation() because the decoded scan carries no source location (the operation type does not require scanning one) and never carries the serial's quant location. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_model.js#L937-L944 For a delivery, that default resolves to the picking's own source location (the parent WH/Stock), so the line is sourced from the parent instead of the sublocation where the serial physically sits. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_picking_model.js#L1542-L1544 On validation the unit is deducted from the parent location instead of the sublocation, leaving a stale quant of the serial in the sublocation and a negative quant at the parent. opw-5864414 Forward-Port-Of: odoo/enterprise#128523 Forward-Port-Of: odoo/enterprise#121375
The Swiss payroll module no longer assigns a Swiss contract type by default when the employee or company context is not Swiss. This prevents incorrect employee contract information and avoids related automated test failures.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#127830
Forward-Port-Of: odoo/enterprise#126520Point of Sale now correctly validates negative orders that were manually paid with standard methods such as card payments. This prevents users from being wrongly blocked by a customer selection popup when the first payment option is Customer Account.
Original PR description
Validating a negative order manually paid with a standard method (e.g., Card) mistakenly triggers the fast payment fallback. The system wrongly assumed any single negative payment line was an auto-generated unsettled due. As a result, if the first configured payment method is "Customer Account", validation is incorrectly blocked by a popup asking for a customer. This commit restricts the fast payment trigger for negative amounts to only apply when the existing line is specifically a 'pay_later' type. task-6443347 Forward-Port-Of: odoo/odoo#282844 Forward-Port-Of: odoo/odoo#281238
Fixes an editor display issue where gradient-styled text inside a link could disappear when selected. Users editing website or email content can now clearly see linked text during selection, reducing confusion and editing mistakes.
Original PR description
Problem: When text formatted with `.text-gradient` is inside a link with `.o_link_in_selection`, the selected text becomes invisible. `.text-gradient` sets `-webkit-text-fill-color: transparent`, which prevents `color: black !important` on `.o_link_in_selection` from taking effect. Cause: `-webkit-text-fill-color: transparent` from `.text-gradient` overrides standard text `color` rendering, causing the text to stay transparent against the selection highlight background. Solution: Set `-webkit-text-fill-color: black` on `.o_link_in_selection` to ensure text inside gradient links is rendered in black and remains clearly visible when selected. Steps to reproduce: - Add text "ABCD". - Apply gradient color to all text. - Create a link on "BC". - Place cursor/selection inside the new link. - Observe that the text is not visible. opw-6479350 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282952
Users on the Android mobile app can now download images and other files opened from Odoo without seeing an unsupported download error. The change sends eligible file downloads through the mobile app's supported download path, improving a visible workflow in Discuss and file viewing.
Original PR description
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads…
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads using the HTTP protocol." downloadFile()'s GET-by-URL case fetches the URL via XHR, then saves the Blob response by clicking a hidden <a download> anchor on a blob: URL. Android's DownloadManager only accepts http(s) URLs, so it rejects that blob: URL instead of downloading anything. Patch downloadFile._download to hand the URL directly to a new mobile.methods.saveFile bridge method when available, the same way download._download already delegates to mobile.methods.downloadFile. Blob/string content downloads aren't handled here — the only such call site (spreadsheet JSON export) is debug-mode only, so this is left as a console.warn for now. Related to odoo/odoo@e83fd8c08c879f5e262d39f24edcb3f81238ea82 Code made by Claude Changes supervised by HUVW Forward-Port-Of: odoo/enterprise#128471 Forward-Port-Of: odoo/enterprise#127693
Belgian payroll now avoids showing a missing transport benefit warning for company executives. This prevents an incorrect alert from appearing on executive contracts where the rule should not apply.
Original PR description
The transport benefit warning incorrectly applies to company executives (Joint Committee = 999). This warning is intended solely for regular employees. Steps to reproduce: 1. Go to an employee's contract and set the Joint Committee to 999. 2. Set a monthly wage that results in an annual salary below 34,654€. 3. Ensure no transport benefits are selected. 4. Save the contract; the missing transport benefit warning is incorrectly displayed. This change skips the validation for Joint Committee 999 to ensure the warning only triggers when applicable. task-6442880 Forward-Port-Of: odoo/enterprise#126642
Projects linked to both standard sales orders and rental orders now show the full list when users open the Sales button. This makes the displayed sales count match the actual orders shown, reducing confusion for teams managing rental-related projects.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Observe the "Sales" stat button counts 2 Sales. 4. Click the stat button. Only the standard Sales Order is displayed. Issue --- In saas-18.4, the project Sales stat button calls action_view_sos without the from_embedded_action context key. As a result, _get_sale_orders_domain applies the non-rental filter by default, causing rental orders to be excluded from the action even though they are included in the displayed counter. Expected Behavior --- The Sales stat button should display all orders linked to the project, including both standard and rental orders, matching its total counter. Fix --- Return the base project domain unmodified when from_embedded_action is not set in the context. task-6140201 Forward-Port-Of: odoo/enterprise#128468 Forward-Port-Of: odoo/enterprise#121449
Products with a base price of zero but paid attribute options are now correctly recognized as having a sellable price. This prevents shoppers from being blocked when adding these configured products to their website cart while zero-price sale prevention is enabled.
Original PR description
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never`…
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is raised. Root cause: --- - In `_is_add_to_cart_allowed()`[1], the method calls `_get_contextual_price()` [2] to check if the product's price is zero when `prevent_zero_price_sale` is enabled. - However, `_get_contextual_price()` is called without the no-variant attribute values in the context, so it does not account for their `price_extra`. For a product with list price as 0 and attribute with extra price, the price is incorrectly computed as 0, causing `_is_add_to_cart_allowed()` to return `False`. Solution: --- - Before calling `_is_add_to_cart_allowed()`, set the product's context with the no-variant attribute values via `_get_product_price_context()`, so that `_get_contextual_price()` correctly includes the price extra in its computation. [1]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/controllers/cart.py#L117-L120 [2]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/models/product_product.py#L149-L150 opw-6365566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283491 Forward-Port-Of: odoo/odoo#278620
The LinkedIn social integration now handles cases where LinkedIn returns no account statistics. This prevents refresh failures and helps users keep their social account data up to date reliably.
Original PR description
Bug === When the LinkedIn API returns no statistics for the account, the refresh crashes. Task-6425391 Forward-Port-Of: odoo/enterprise#126326
The AI assistant for drafting social posts no longer crashes when preparing the request context, especially when using Google-backed AI services. This helps users reliably ask AI for help writing social content without interruption.
Original PR description
Bug === The `aiChatSourceId` contains `datapoint_x`. Also, look like now we should `json.dumps` the initial context. Task-6485440 Forward-Port-Of: odoo/enterprise#124832
Fixed an issue where inserting an AI-generated image from the media dialog could cause an error. This helps users complete social post content creation smoothly without being interrupted by a crash.
Original PR description
Bug === Since odoo/odoo@7427089969ab445dc86e37d628c9c59e7c73c632 , when we open the media dialog, click on the AI button, generate an image and then insert it, a traceback is raised. Task-6432288 Forward-Port-Of: odoo/enterprise#126229