Monday, August 25, 2025
31 changes · saas-18.3
Resolved issues and error corrections
The Unsplash image picker now handles cases where Unsplash returns the same image more than once in a search result. This prevents users from seeing a crash when browsing image search results, such as searches for “Inventory”.
Original PR description
This commit fixes an OwlError when we try to render the images received from Unsplash after a search. The issue is that Unsplash can send duplicate images in the same batch of images. When we render those in a `t-foreach` and use the image `id`s as the keys, we get a duplicate key error. This is fixed by expanding on the previous filtering code, which ignored duplicates over multiple batches. We now ignore duplicates within batches as well. At the time of writing, Unsplash is sending us duplicate images on a search for "Inventory". opw-5027032 Forward-Port-Of: odoo/odoo#223789
Saudi electronic invoicing no longer blocks invoices when the invoice company differs from the journal company in standard branch setups. This helps businesses using branches generate the correct QR code and process invoices without unnecessary restrictions.
Original PR description
This commit removes the previously enforced restriction in https://github.com/odoo/odoo/commit/d6175d0552c18006913e969eac7006666164609c that required the company specified on an invoice to match the company specified on the associated journal and makes sure that the company used to create the QR is the appropriate company whether in a branch or in a main company task-5005477 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223976 Forward-Port-Of: odoo/odoo#222935
This fix prevents the multi-employee time off and allocation wizard from carrying over navigation details from an unrelated leave request. Users will now see clearer breadcrumbs and URLs when generating time off or allocations for multiple employees.
Original PR description
Task ID: 5004005 **Description of the issue this PR addresses:** When generating time off or allocations for multiple employees using the wizard, the resulting breadcrumb and navigation incorrectly inherit the active_id from the parent view (a specific leave request) appearing as a child of a specific leave record in the breadcrumb and URL. Forward-Port-Of: odoo/odoo#222764
Product pages no longer show a delivery truck or delivery status when the only available option is in-store pickup. This avoids confusing shoppers by only showing delivery information when home delivery is actually supported.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Disable all delivery methods except for "Pick up in store"; 2. go to a product page. Issue ----- A delivery truck is shown with its delivery status, even though delivery is not supported. Cause ----- The `delivery_stock_data` info looks for all published "delivery" carriers, including `in_store` types, which is already covered by `in_store_stock_data`. Solution -------- - Exclude `in_store` delivery types when looking for delivery carriers. - If the `deliveryStockData` object is empty, don't render the truck. opw-5010081
This fixes a Point of Sale startup error that could occur when the default sales preset required a customer to be selected. Stores using this setup can now open POS sessions normally, reducing disruption at checkout.
Original PR description
Before this commit, if the POS default preset required a partner, an error would occur during initialization. opw-5023987 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix adjusts where action buttons appear on log notes written by the current user. It makes the message layout more consistent and easier to use by placing actions on the correct side of the timestamp.
Original PR description
**Purpose of this PR:** Fix the position of message actions on log notes authored by the current user. Messages authored by self appear on the right side of the thread. This PR mirrors the action placement logic so that, like messages from others (which show actions to the right of the date), self-authored messages show actions to the left of the date. Before: <img width="392" height="638" alt="image" src="https://github.com/user-attachments/assets/8b66c98f-3e00-47c8-abf3-ee62169ed499" /> After: <img width="392" height="638" alt="image" src="https://github.com/user-attachments/assets/d1a425da-fb0c-4793-a080-735286bc2bb9" /> task-[4689357](https://www.odoo.com/odoo/project/1519/tasks/4689357) Forward-Port-Of: odoo/odoo#223788 Forward-Port-Of: odoo/odoo#216520
Leads without a valid email will now only be sent for enrichment once. This prevents repeated failed attempts and avoids ongoing error loops, keeping CRM enrichment activity cleaner and more reliable.
Original PR description
If a lead has no valid email, try to enrich it only once This will avoid infinite loop of errors of "Enrichment could not be done because…" Forward-Port-Of: odoo/odoo#223874
This fixes how order dates are sent for online payments in Point of Sale so they use the expected UTC time. It helps prevent incorrect order timestamps caused by local time zone conversion.
Original PR description
In 2a5f1abf2e98ee09fa7a912b87d71879b5ff260b, we formatted the `order_date` with `toFormat(...)`, however, that transforms the date into local, while the backend expects it to be in UTC. In this commit, we set the date tz back to UTC before formatting it. opw-4942697
The online store now uses smaller product image versions when processing large product lists. This helps prevent out-of-memory errors and improves reliability for shops with many products.
Original PR description
This commit fixes an "out of memory" error caused by loading the `image_1920` field into memory for a large `product.product` recordset. To resolve this, the code has been changed to use `image_128` to limit the memory impact. See also: - https://github.com/odoo/odoo/pull/222584 opw-4981983
Repeated global discounts now ignore tax amounts copied from the original sale order lines, preventing discounts from being calculated too high on already discounted orders. This keeps discount and tax totals accurate when users apply global discounts more than once.
Original PR description
When creating a global discount more than once, the values on the second time onward would be incorrect due to the manual tax amounts being propogated from the sale order lines. This would cause the discount amount to increase when discounting an already discounted sale order. This happened because manual tax amounts that were from the lines that the discount lines were created from were being propogated and used to attempt to find the correct tax amounts up to the target_amount_currency, but this is incorrect. Removing the manual tax amounts when the special type of the line is global_discount resolves this issue and allows multiple global discounts to be used. opw-4985380
Fully flexible employees can now request time off in hours as well as full days. This helps related apps such as Timesheets and Planning accurately record paid holidays and unavailable working periods.
Original PR description
In this PR, we allow fully flexible employees to take time off in hours or days, to allow other apps such as timesheet to encode their paid holidays or planning to use unavailable intervals Forward-Port-Of: odoo/odoo#217938
Accounting now handles manually adjusted tax amounts more accurately when preparing electronic invoices. It also improves how global discounts and returned items are spread across invoice lines, helping country-specific formats such as Mexico's CFDI report amounts correctly.
Original PR description
When using 'manual_tax_amounts', both 'raw_tax_amount' & 'tax_amount' get the forced tax amount. However, by doing that, we lost accuracy in the raw amount. With this commit, the manual_tax_amounts…
When using 'manual_tax_amounts', both 'raw_tax_amount' & 'tax_amount' get the forced tax amount. However, by doing that, we lost accuracy in the raw amount. With this commit, the manual_tax_amounts become a way to ensure some results in '_round_base_lines_tax_details'. So after this commit, the manual_tax_amounts won't be manage in '_get_tax_details' anymore. This commit also adds a new helper '_dispatch_global_discount_lines' that can be used to split the global discount lines across the others base lines. That way in EDI like Mexico, the global discount can be reported line by line as a discount per line and no longer a big discount applied on a single line. There is also another helper '_dispatch_return_of_marchandise_lines' that allows to dispatch negative lines using the quantity. For example, if you buy 3 times the same product but one is returned because broken, you will end up with a sell of 2 products instead of 3 but having a discount of 33.33%. This makes the difference when generating the mexican CFDI. task-id: 4926200 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a Point of Sale issue where starting a new order with a default preset that requires a customer name did not show the name entry popup. Staff will now be prompted as expected, helping restaurants capture the needed customer details for takeout or similar orders.
Original PR description
Steps to reproduce: - go to the setting of your pos.config - set the default preset as takeout (or any other that require the name) - open your pos - click on new order - the slot selection opens (only if set so it's ok) - but then no dialog to enter the name of the client Issue: The handleSelectNamePreset method in the POS Restaurant module attempts to access the selected preset through the order, but the preset has not yet been set on the order at that point. Fix: Make sure the preset is set on the order before calling handleSelectNamePreset. Task-5030520 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
The Point of Sale now handles new orders that do not yet have a preset assigned, avoiding a crash during customer selection or initial order loading. This keeps cashier workflows running smoothly when address-based presets are configured.
Original PR description
STEPS TO REPRODUCE: ---------------- - Open Point of sale - Create preset in the backend with Identification = Address (make it Default). - Open Register - Try to new order and select a customer. ISSUE: ------------------ - Crash occurs if the order has no preset set yet (e.g., during customer selection or initial load). CAUSE: ------------------- - Accessing the preset’s fiscal position and pricelist even when no preset is set. FIX: --------------------------- - Used optional chaining (?.) to safely access preset fields. TASK-5005015
Event calendar slots now keep the intended calendar date when the user and event are in different time zones. This prevents sessions from being created a day late in cases where timezone conversion crosses midnight, improving scheduling accuracy for event organizers.
Original PR description
Purpose ======= Fix the creation of slots at the wrong date. Specification ============= User timezone: Europe/Brussels Event timezone: America/Los Angeles When creating a slot on the calendar on the 10th of April from 8PM to 11PM, the slot is created from 8PM to 11PM but on the 11th of April. In scenario where the conversion from the local tz to the event tz changes the date, the slot is created at the wrong date. => After conversion, the DateTime 'zone' param needs to be set back to the local tz (without changing the converted times) to make sure the calendar renders records correctly as it always expects datetimes expressed in the 'local' tz. related PR: https://github.com/odoo/odoo/pull/205945 Task-4743999 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The French point of sale compliance check now avoids loading extra order data that it does not need. This reduces memory usage substantially for businesses with large numbers of POS orders, helping the report run more reliably.
Original PR description
### Problem: Following this pr https://github.com/odoo/odoo/pull/217348, field prefetching is unnecessary when fetching orders, as all required fields are already fetched explicitly. Keeping prefetching enabled causes excessive memory usage. ### Benchmark | Orders | Before | After | |--------|---------|--------| | 1k | 6MB | 5.8MB | | 10k | 42MB | 27MB | | 100k | 534MB | 320MB | | 200K | 1.1GB | 646MB | opw-4901994 Forward-Port-Of: odoo/odoo#223535 Forward-Port-Of: odoo/odoo#222416
Opening a project could fail after a related app, such as Timesheets, was uninstalled because a saved embedded action still referred to fields from that app. The change safely hides unavailable embedded actions instead of crashing, allowing users to keep working normally.
Original PR description
The system failed to evaluate the embedded action, which refers to the Uninstalled module.
**Steps to produce:-**
- Install `Project` and `Timesheets`.
- Go to Project and open any project.
- Click on the `embedded action` icon and select Timesheets.
- `Save` the view from the `embedded action's icon`.
- Now, `Uninstall Timesheets`.
- Now, go to that Project and try to open it.
**Error:-**
`KeyError: 'allow_timesheets'
ValueError: Invalid field in filter of project.project:
[('allow_timesheets', '=', True)]`
**Solution:-**
- Added a safe check using `hasattr` to verify if the `python_method` defined on the embedded action actually exists on the specified model.
- Ensured that if the method is missing or invalid, the embedded action is marked as not visible instead of causing a crash.
**sentry-6738596751**
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#218564Fixed a website header display issue where certain navigation link styles made the sign-in button appear larger than intended. This keeps the header layout consistent after editing link style options, improving the visual polish for visitors and users.
Original PR description
Before this commit, using the "outline" or "border bottom" options for the Link Style (active page link in the header) would make the sign in button bigger. This was due to the fact the selector was not precise enough and would also include the button. This commit improves the selector to avoid impacting the sign in button. Steps to reproduce: - Go to Edit mode - Click on the header - Set the Navbar > Links Style option to "Border Bottom" - Save - Log Out Forward-Port-Of: odoo/odoo#223441
Installing the Belgium Accounting localization no longer fails when a referenced demo account tag was previously deleted. This makes setup more reliable for demo or test environments where sample accounting data may have been changed.
Original PR description
Currently, installing the Belgium Accounting localization fails with an error, if the user has deleted referenced demo account tags. **Steps to reproduce:** - Install the Accounting app. - Delete the "Demo Capital Account" account tag. - Install the Belgium Accounting localization (`l10n_be`). **Error:** `ValueError - External ID not found in the system: account.demo_capital_account` At [1], if the `account.demo_capital_account` is not found, it raises an error if the external ID is missing. This commit prevents the error by explicitly passing `raise_if_not_found=False` and skipping the tag if not found. [1] - https://github.com/odoo/odoo/blob/71d1c9a4bef1c29485e3b0390713a9301ad6db4f/addons/l10n_be/demo/account_demo.py#L13-L19 sentry-6776341713 Forward-Port-Of: odoo/odoo#221227
This update corrects the help link in Timesheets settings after the related documentation page was moved. Users clicking the information icon for time off settings will now be taken to the right documentation instead of a broken or outdated page.
Original PR description
**Description:** - In a recent documentation commit, the overview section was removed from the timesheets path. commit: odoo/documentation@3bceee836fa8b8edfd8a35c20b21867354f6c078 **Steps to reproduce:** - In a `v18` runbot - open settings > Timesheets settings > under Time off - click on the info icon <img width="1905" height="944" alt="2025-08-21_18-25" src="https://github.com/user-attachments/assets/34ec76ed-46f7-4b08-8c23-10269e105b43" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#223711
Fixes an issue where removing text color or formatting in the HTML editor could cause the editor to get stuck. This makes editing content more reliable, especially when formatting is applied to larger text blocks or non-editable elements are selected.
Original PR description
**Current behavior before PR:** - When color was applied to a block-level element, attempting to remove it caused the `removeFormat` method to enter an infinite loop. - Removing formatting on a contenteditable false element infinite loop when removing format. **Desired behavior after PR is merged:** - Now, the color is correctly removed from the selected text, even when it is applied to a block-level element. - Now, the toolbar no longer opens when the selected element is contenteditable false task: 4575459 Forward-Port-Of: odoo/odoo#223786 Forward-Port-Of: odoo/odoo#198319
Restaurant table appointments are now correctly loaded in the Point of Sale when restaurant mode is enabled. This ensures staff can see upcoming table bookings on the floor plan, reducing missed reservations and improving service coordination.
Original PR description
Issue: The calendar envents that have a restaurant table ressource are not loaded in the pos if the config is in restaurant mode. Fix: If the config is a restaurant the calendar_event pos domain will return a domain containing the appointment_ressources linked to the config restaurant tables. This commit also fixes the test that checks for the appointment-label on the floor plan. Task-id: 4970986
Knowledge articles now save any pending edits before the page refreshes after moving another article nearby. This prevents users from accidentally losing their work and makes article editing more reliable.
Original PR description
Currently, when a user moves another article beneath the one they are editing, the record is reloaded, causing any unsaved changes to be lost. This can be especially frustrating if the user has made significant edits. To address this issue, we will ensure that any changes made to the article are saved before the record is reloaded. This will prevent accidental loss of work and improve the editing experience. Steps to reproduce the issue: 1. Open an article 2. Make changes to the article (e.g, type or edit text) 3. Drag and drop another article beneath the current one. => The article reloads, and your unsaved changes are lost. In the `moveArticle` function, we will check if the record has unsaved changes (i.e., if it's "dirty"). If so, we will save the current content before triggering a reload via `this.props.record.model.load()`. Task-4636494 Forward-Port-Of: odoo/enterprise#87937
Creating a bank statement now works even when the Bank journal has no outstanding receipt or payment account configured. This prevents an error screen and lets accounting users continue their workflow in setups where those accounts are intentionally left blank.
Original PR description
**Steps to reproduce:** - Install Accounting - Make sure that no outstanding receipt/payment account is configured on the Bank journal - Go to the Bank journal - Create a new statement **Issue:** A traceback is raised while executing a SQL query. **Cause:** A IN condition is evaluated with an empty tuple: `AND aml.account_id IN ()` This is due to the fact that there is no outstanding account. **Solution:** Only execute the SQL query if there is an outstanding account. opw-5039931
Fixed an issue where automatic subscription invoicing could stop too early when a limited batch included subscriptions that were not ready to invoice. The scheduler now applies the limit after checking invoice eligibility, helping ensure ready subscriptions are invoiced on time.
Original PR description
Change was introduced here https://github.com/odoo/enterprise/pull/82340 that caused the cron trigger to not be activated if any of the 31 in the batch of subscriptions found was not to invoice. This is problematic because there could be other subscriptions that meet the domain requirements and the to invoice requirements that are not being seen because the limit is on the search before we check invoiceability. Added a limit to _get_subscriptions_to_invoice instead of on the search in order to take into account both filters for next cron triggers. opw-4850884 Forward-Port-Of: odoo/enterprise#92690 Forward-Port-Of: odoo/enterprise#89787
Planning calendar invites can now be exported even when a shift has no assigned employee. The system uses a safe default timezone instead of failing, reducing interruptions when publishing or sharing open shifts.
Original PR description
Currently, an error occurs when a user tries to export a calendar invite (ICS) for a planning shift that has no assigned resource. **Steps to reproduce:** - Install the `planning` module. - Go to `Planning > New`, and click `Publish & Send`. - Enable developer mode and go to `Settings > Technical > Email > Emails`. - Open the latest email record and click `iCal/Outlook`. **Error:** `AttributeError: 'bool' object has no attribute 'upper'` **Root Cause:** At [1], when no employee is assigned to the shift, `slot.employee_id` is `empty`, so `slot.employee_id.tz` is `False`, which leads to an error. This commit ensures a valid timezone is always used by selecting the current user's timezone or 'UTC' when the shift has no assigned employee. [1] https://github.com/odoo/enterprise/blob/13ce65b8ca61f9a825f2876e2727cddfae83f894/planning/controllers/main.py#L355 sentry-6781639319 Forward-Port-Of: odoo/enterprise#91889
Purchase bills matched by their IRN number no longer trigger an error during processing. This improves reliability for Indian GST reporting workflows by ensuring bill matching can complete successfully.
Original PR description
Before this IR: - When a purchase document was matched using the IRN number, the variable `matching_keys` was not defined. - This led to an `UnboundLocalError` during bill matching. After this PR: - `matching_keys` is now set together with the IRN number. - This ensures `matching_keys` is always available and prevents runtime errors when IRN matches bills. opw-5037128
Users with standard Appointment access can now create resource-based appointments from calendar events without hitting an access error. This restores the expected booking flow when an appointment type has a single resource, reducing disruption for staff managing appointments.
Original PR description
Before this commit, trying to create an appointment through a calendar event as an user will raise an AccessError. This is because in this fix #76653 we needed to make sure the appointment_resource_id is being set on the calendar event and for this we needed to make it readonly. This causes that an user, is not able to get the proper access rights to read on to the 'appointment.booking.line' which is being triggered since inside each booking line, we have an appointment_resource_id which is a many2one to the appointment resource. To fix this, we are adding a sudo on the booking lines when we only have 1 booking line and the appointment resource is set on the calendar event. This way, the user will be able to read the booking lines and create the appointment. opw-4614976 Forward-Port-Of: odoo/enterprise#90149 Forward-Port-Of: odoo/enterprise#88373
The Indian Payroll yearly salary report now handles translated salary structure names correctly. This prevents an error when users print the report after creating and paying payslips, helping payroll teams access annual salary details reliably.
Original PR description
Steps to Reproduce:
- Install Indian Payroll Localization
- create a payslip of any employee and mark as paid
- try to print yearly salary report from reporting menu
Issue:
- A traceback error occurs when printing the yearly salary report.
Reason:
- the sturcture name is translatable field, which gives the value in a dict with the key as languages like {'en_US': 'India: Regular Pay'}.
- The error occurs because the code attempts to use this dictionary with setdefault, which expects a string.
Solution:
- Get the structure name corresponding to the appropriate language from the dictionary before passing it to setdefault.
task-5002518Payroll configuration screens now show Python code correctly for salary rules and rule parameters. This helps payroll administrators review and maintain calculation logic more reliably, reducing confusion when checking payroll setup.
Original PR description
Forward-Port-Of: odoo/enterprise#92960 Forward-Port-Of: odoo/enterprise#91811
Helpdesk ticket portal pages no longer show an unrelated Timesheets breadcrumb when a ticket includes logged time. This keeps customer navigation clearer and avoids confusion when viewing support tickets online.
Original PR description
**Steps to reproduce:** 1. Install 'Helpdesk Sale Timesheet' and 'Website' modules. 2. Create a helpdesk ticket and add timesheets to it. 3. Go to the portal view of helpdesk tickets. **Issue:** If the ticket contains timesheets, the "Timesheets" breadcrumb appears in the portal ticket view. **Cause:** The reason the timesheet variable is used in the hr_timesheet portal template is because it makes the condition evaluate to true, which is why the breadcrumb for Timesheets is displayed. **Fix:** Renamed the loop variable in `t-foreach` to avoid shadowing the `timesheet` variable from the outer context. task-4744294 Forward-Port-Of: odoo/enterprise#85411