Friday, August 1, 2025
24 changes · saas-18.4
Enhancements to existing features
Users are now notified when an IoT-connected device is disconnected instead of actions simply failing silently. This makes device issues clearer and helps users understand why an operation could not be completed.
Original PR description
If a device is disconnected, we had no way of telling the user, we only didn't perform the action. Now we notify the user that the device is disconnected. Enterprise PR: odoo/enterprise#91419 Task: 4978644
Point of Sale users in Belgium now see a clearer disconnection message when the fiscal blackbox cannot be reached through the IoT Box. The dialog includes a retry option, helping staff continue order validation or clock in/out once the connection is restored.
Original PR description
We improved the dialog telling the user its blackbox is disconnected from the IoT Box. We added a retry button to allow retrying validation of an order and clocking in/out. Community PR: odoo/odoo#221345 Task: 4978644
Resolved issues and error corrections
Payments through Authorize.Net and AsiaPay no longer crash when a payment provider has no currency configured. This helps customers complete payment flows more reliably and avoids an error during payment link checkout.
Original PR description
The system crashes when an `authorize.net` payment provider has no currency configured and user try to make payment. **Steps to reproduce:-** - Install `Sales` module. - Install the `Authorize.net` as a `payment provider`. - Set the mode as `Test mode` > set credentials > click on `Generate Client Key`. - `Configuration page > remove the currency and save`. - Now, go to any sale order > click on the gear icon > click `generate payment link` > and try to pay on that link using a card. **Error:-** `IndexError: tuple index out of range` **Solution:-** - In this commit, we checked that if currency is present then we will call `_validate_amount_and_currency` otherwise we skip it. **sentry-6757453610** I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Timesheet administrators who do not have Project app access can now open timesheet lists and related forms without being blocked by permission errors. This keeps timesheet review workflows available while respecting existing project access restrictions.
Original PR description
Steps to Reproduce: - Ensure the `sale_timesheet` module is installed. - Log in as a user with Timesheet Administrator permissions but without access to the Project module. - Attempt to open the…
Steps to Reproduce: - Ensure the `sale_timesheet` module is installed. - Log in as a user with Timesheet Administrator permissions but without access to the Project module. - Attempt to open the Timesheets list view results in an `AccessError` due to missing read rights on `project.task`. - Create a task in a private project linked to a timesheet and open its form view results in an `AccessError` due to missing read rights on `project.project`. Cause: - When a user has Timesheet Administrator access but lacks project access, they can view all timesheets, including those linked to tasks with private privacy visibility. However, these users do not have read access to the private tasks themselves. - The `_compute_commercial_partner` method reads `task_id.partner_id.commercial_partner_id` and `project_id.partner_id.commercial_partner_id`. When a user without read access to `project.task` or `project.project` tries to compute this field, an `AccessError` occurs because the code tries to access these related records without bypassing access rights. Solution: - Use `sudo()` on `task_id` and `project_id` when accessing their `partner_id` fields inside the compute method to bypass access rights checks, preventing ` AccessError` for users lacking read permissions. task-4798066 Forward-Port-Of: odoo/odoo#221247 Forward-Port-Of: odoo/odoo#210826
The Point of Sale now waits briefly before checking connectivity after an internet interruption, avoiding a false offline state. Once the connection is restored, it automatically triggers order synchronization so sales data is sent to the backend without manual intervention.
Original PR description
Steps to reproduce: - open a pos on a runbot from saas-18.2 - turn off the wifi on your device until you see the disconnected sign - turn back on the wifi - the pos stays in "offline" mode Issue: The ping rpc call is made before the connection is really reestablished. The rpc call fails and the network.offline attribute stays true. This prevent the data from being sent to the backend. Fix: Set a timeout to perform the ping rpc call and sent an envent to notify the pos_store to syncAllOrders when back online. Task-id: 4978122 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#220954
This fix ensures activities already marked as done are not counted as overdue or due soon in activity searches and menus. It improves accuracy for teams that keep completed activities for reporting, preventing misleading follow-up counts while preserving access to archived CRM leads where needed.
Original PR description
The search for "my_activity_date_deadline" is used to find activities due before some set date. When keeping done activities for reporting purposes, we should never consider "done" activities for this search. Issue is introduced in CRM in [1] but it could happen anywhere task-4951716 [1]: https://github.com/odoo/odoo/commit/f9f0529c93614bb9f9deec1a5aaa1daccfe8b58c Forward-Port-Of: odoo/odoo#220600 Forward-Port-Of: odoo/odoo#219426
Creating vendor bills from multiple purchase orders no longer crashes when the selected orders belong to different vendors. The system now only pre-fills a vendor when all selected purchase orders use the same vendor, allowing users to continue billing safely from the list view.
Original PR description
Bug introduced by: https://github.com/odoo/odoo/commit/b75394102bec3e25b23c75fd82ca0d8dec2726c5#diff-1281da5f4d0a3daaf162a2e6456469537d1b74b8034437783c9c717307aa8fcdR859 Steps to reproduce: - Create…
Bug introduced by: https://github.com/odoo/odoo/commit/b75394102bec3e25b23c75fd82ca0d8dec2726c5#diff-1281da5f4d0a3daaf162a2e6456469537d1b74b8034437783c9c717307aa8fcdR859 Steps to reproduce: - Create two purchase orders with different vendors - Add any product and confirm both orders - From the purchase order list view, select both orders - Click on "Create Bill" Problem: A traceback occurs when selecting multiple purchase orders with different vendors and clicking Create Bill from the list view. This is due to default_partner_id being forcibly set in the context, which assumes a single vendor. This bug was introduced by commit b753941, where default_partner_id is always injected into the context, even when multiple vendors are involved: https://github.com/odoo/odoo/commit/b75394102bec3e25b23c75fd82ca0d8dec2726c5#diff-1281da5f4d0a3daaf162a2e6456469537d1b74b8034437783c9c717307aa8fcdR714 Why it breaks: When creating a bill, action_view_invoice() is called without verifying that only one vendor is selected. Setting a default_partner_id in such cases leads to invalid assumptions and crashes. Difference with attachments case: When uploading bills from attachments, a check does ensure a single vendor is selected before calling action_view_invoice() (see b753941#R714). Fix: Only inject default_partner_id into the context if all selected purchase orders share the same vendor. opw-4948142
Turkish Nilvera e-invoices now include clearer currency exchange-rate information when issued outside TRY and correctly show total discounts. The XML format was adjusted to match Nilvera requirements, helping invoices be accepted and preserving the correct payable amount.
Original PR description
This commit does following fixes for e-invoice XML generated for Nilvera. - adds currency exchange rate as note in XML if invoice currency is other than TRY. - adds total discount amount at the Invoice document level. - creates a new XML template for TR e-invoice inherited from the UBL Invoice Template. - removes the `<cac:PrepaidAmount>` node as it is not a valid node in Nilvera and adds the node value to `<cac:PayableAmount>` so that actual invoice amount is preserved while sending e-invoice. TaskID:4815875 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#220815 Forward-Port-Of: odoo/odoo#216594
This fix brings back the Position option for images in website grid layouts, so users can again control how images fit inside grid blocks. It also prevents an error when switching grid items back to normal mode, improving reliability in the website builder.
Original PR description
Since commit [1], the "Position" grid image option is not appearing anymore, making it impossible to change the `object-fit` property of the grid item images, making them forced to always be in…
Since commit [1], the "Position" grid image option is not appearing anymore, making it impossible to change the `object-fit` property of the grid item images, making them forced to always be in `cover`. The fix of commit [1] was made to avoid a traceback when toggling back to normal mode, because the `isApplied` was run after the grid mode was disabled but before the option noticed that it was not supposed to be there anymore. However, this was not the right fix, as it made the option not appear at all. This commit removes this previous fix and fixes the issue by simply checking if the `o_grid_item_image` element is well present in `isApplied`(as it was done before the refactoring). This commit also cleans the code a bit and renames the files/component/plugin/action so they are called `grid_image_` instead of `image_grid_`, to be more correct and to make the link with the old code. [1]: https://github.com/odoo/odoo/commit/82882b7e3e24951aa7224a3a266e57cc4773e546 task-4367641
This change restores the previous handling of subcontracted product moves to avoid breaking backorders when a delivery contains both regular and subcontracted products. It prioritizes keeping barcode operations workable, while any remaining backend issue can still be corrected manually by users.
Original PR description
This commit reverts db8b33e (and the wrong follow-up fix of 2755c09) because it breaks backorders for pickings that mix regular and subcontrcted products. We'd rather the flow has problems in back end where the user can manually uncheck the picked box rather than in barcode where there is no work around. We keep the enterprise test introduced in [792c968](https://github.com/odoo/enterprise/commit/792c968) to protect the barcode flow. Forward-Port-Of: odoo/odoo#220318
Free self-service POS orders are now processed the same way as paid orders for fulfillment purposes. This ensures stock picking and preparation records are created even when the customer owes nothing, preventing missed order handling.
Original PR description
Steps to reproduce: ------------------- 1. Create a free product 2. Add it to self_order 3. Make a self order with only that product -> Free order Sicne it's a free order, you will not be asked to…
Steps to reproduce: ------------------- 1. Create a free product 2. Add it to self_order 3. Make a self order with only that product -> Free order Sicne it's a free order, you will not be asked to pay, which is normal. However, the issue is, no picking is created for that order!! Why the issue? -------------- For a non free self order, we create a picking for it by calling `_process_saved_order` [1] with `draft` argument set to `True`, either after paying using the online payment method [2], or after paying it from the payment wizard [3]. However, since for free orders, we're not asked at any point to pay, and hence, we're not calling `_process_saved_order` with `draft=True` at any point, and as consequence, we're also not calling `_create_order_picking`, no picking will be created for it. The fix ------- After, marking the free order as 'paid', we manually call `_process_saved_order(True)`. We only do it for the free orders, since the flow is working as expected for non-free order. [1]: https://github.com/odoo/odoo/blob/a7a29ed691db4f1607c0d12929c56845681164fa/addons/point_of_sale/models/pos_order.py#L153C19-L153C31 [2]: https://github.com/odoo/odoo/blob/a7a29ed691db4f1607c0d12929c56845681164fa/addons/pos_online_payment/models/payment_transaction.py#L64 [3]: https://github.com/odoo/odoo/blob/a7a29ed691db4f1607c0d12929c56845681164fa/addons/point_of_sale/wizard/pos_payment.py#L70 opw-4739523 Forward-Port-Of: odoo/odoo#221434 Forward-Port-Of: odoo/odoo#218118
Point of Sale now calculates lot availability using only stock from the configured PoS source location and its internal child locations. This prevents cashiers from seeing or selling quantities that exist elsewhere but are not actually available to that PoS location.
Original PR description
The get_existing_lots function previously returned product_qty based on stock.lot's computed field, which sums quantities from all locations. This led to incorrect available quantities in the PoS, as it should only consider stock in the configured PoS source location and its child internal locations. opw-4865777 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#219444 Forward-Port-Of: odoo/odoo#215227
Dates shown in website content can no longer be edited directly from the builder. This prevents users from accidentally breaking date displays while editing pages such as blog listings.
This fix ensures that when a sales order is settled in Point of Sale, the latest order line quantities are used instead of outdated cached values. This prevents cashiers from charging based on old quantities after a sales order was changed elsewhere.
Original PR description
Steps to reproduce ------------------ 1. Create a Sales Order, add a product with QTY = X 2. Open PoS 3. Load this same Sales order (by clicking "Settle the order"-> QTX is X as expected 4. Return to…
Steps to reproduce ------------------ 1. Create a Sales Order, add a product with QTY = X 2. Open PoS 3. Load this same Sales order (by clicking "Settle the order"-> QTX is X as expected 4. Return to Sales order (in the sales app) 5. Edit QTY from X to Y and save 6. Go back to PoS 7. Delete the laoded Sales Order and load it again -> Notice that QTY is still X and not the updated Y!! Other Flow in frontend ---------------------- 1. Create a Sales Order, add a product with QTY = X 2. Open PoS 3. Load this same Sales order (by clicking "Settle the order"-> QTY is X as expected 4. Change the quantity manually, to pay for X - 1 5. Validate and pay for the order 6. Load the same Sales order again with "Settle the order" -> The quantity is still X and the price is the unit price times X!! Why the issue ------------- When settling the order, we get its value using _getSaleOrder which basically reads it from the cache. So it will read the old order lines having the old qty, and not the updated one. The fix ------- Instead of reading the lines from the cache, we read them direcly from the backend, to accomodate for cases where the data might have been changed on another device or has not been updated in the cache. opw-4819708 opw-4913397 Co-authored-by: Arthur Nanson <artn@odoo.com> Forward-Port-Of: odoo/odoo#220813 Forward-Port-Of: odoo/odoo#218331
This fixes a problem that could prevent users from printing PDF documents from Android mobile browsers. The change gives Android print previews enough time to finish preparing the document, reducing failed or incomplete print attempts.
Original PR description
Currently, pdf.js does not support printing from mobile browsers, and the pdf.js team will not fix this issue [1]. I investigated and found that sometimes `window.print()` is asynchronous [2]. On Android, the print preview dialog re-renders the entire PDF within the preview, which can obviously take some time and the abort method is call before the preview rendering is complete. opw-4190135 [1]: https://github.com/mozilla/pdf.js/issues/12020 [2]: https://github.com/mozilla/pdf.js/blob/2d0ba7db08fb6bb597ba718635314d8e8998a7d0/web/pdf_print_service.js#L226 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#221172 Forward-Port-Of: odoo/odoo#217526
Chat call windows now keep video streams large enough to view clearly when no participant is selected as the main card. This makes video calls easier to follow by prioritizing visible video content over small avatar-sized tiles.
Original PR description
Before this commit, when in a discuss call in a chat window with at least 1 video, clicking on no main card had all cards sized for avatar, including the video stream. This is a problem because the…
Before this commit, when in a discuss call in a chat window with at least 1 video, clicking on no main card had all cards sized for avatar, including the video stream. This is a problem because the video stream are very small, barely visible, which is unfortunate because when there are video streams they are usually the most important thing that call participants want to see. This commit fixes by adding a new CSS rule in chat window with call: when user in a call with at least 1 video stream, the size of call view matches the size of a 16:9 video stream when focused. Part of task-4967123 Before / After <img width="381" height="634" alt="Screenshot 2025-07-28 at 17 57 37" src="https://github.com/user-attachments/assets/878bae9f-01e5-4f81-9d61-b43180d4f809" /> <img width="385" height="637" alt="Screenshot 2025-07-28 at 17 57 17" src="https://github.com/user-attachments/assets/0261d716-e52c-4a72-ad6a-007c8d01a362" /> Forward-Port-Of: odoo/odoo#221124 Forward-Port-Of: odoo/odoo#220873
Manufacturing orders with very small work center costs could fail during validation because totals were rounded inconsistently. The fix ensures costs are rounded before being added, preventing accounting imbalance errors and showing the correct value in the manufacturing overview.
Original PR description
Steps to reproduce:
- Create two work centers with different expense accounts:
- First: hourly cost of 0.01
- Second: hourly cost of 0.01
- Create an MO for a product with real-time valuation and 2 work orders
(one per work center).
- Each work order has an expected duration of 30:02
- Attempt to click on "Produce All" button.
This leads to an unbalanced move error.
This fix rounds the values before summing them to prevent rounding issues
and unbalanced moves. It also corrects the displayed value in the
Manufacturing Order overview.
opw-4631409
Forward-Port-Of: odoo/odoo#221083
Forward-Port-Of: odoo/odoo#211128Users who manage timesheets but do not have Project app access can now open Timesheet list and kanban views without being blocked by an access error. This keeps time tracking workflows available for administrators while respecting project permissions.
Original PR description
Steps to Reproduce: - Ensure the `timesheet_grid_holidays` module is installed. - Log in as a user with Timesheets Administrator access but no access to the Project module. - Navigate to the Timesheets > List or Kanban view. - An `AccessError` occurs due to missing read rights on the `project.task` model. Cause: - In the `timesheet_grid_holidays` module, the `_should_not_display_timer` method accesses `self.task_id.is_timeoff_task` without checking access rights, causing an `AccessError` when users who can view timesheets but lack read access to `project.task` try to access tasks linked to projects with private privacy visibility. Solution: - Use `sudo()` when accessing `self.task_id` in `_should_not_display_timer()` to avoid access errors. task-4798066 Forward-Port-Of: odoo/enterprise#91361 Forward-Port-Of: odoo/enterprise#86302
Changing the date of a recurring planning shift linked to sales no longer causes an error. The system now ignores shifts that were removed during the update, allowing users to safely edit all recurring shifts without disruption.
Original PR description
Version: 17.0 Steps to reproduce: - Install sale_planning - Create a recurrence shift. - Change the date of second shift which is created by recurrence. - Give the edit value as All shifts. - save record, missing error occured. Issue: When a user changes the date of a shift created by recurrence, the system crash with the message, "Record does not exist or has been deleted." Cause: There was an issue between "Planning" and "Sale Planning". When a user moves a shift, "Planning" removes the old shift from the system except the first one, But 'sale planning' was still trying to work with that removed shift. Fix: Now, after 'Planning' does its work, 'Sale Planning' checks again to see that shifts are still there. It only works with shifts that actually exist. So crash no longer happens. Users can now safely change the date of recurring shifts without errors. task-4859892 Forward-Port-Of: odoo/enterprise#91236 Forward-Port-Of: odoo/enterprise#88234
Users with timesheet access can now start and stop timers on tasks they are allowed to access, even when the related project is private. This prevents access errors during timesheet confirmation and keeps field service time tracking working as expected.
Original PR description
Before this commit, when the project is private and the user can only access to some tasks inside that project, he can create timesheets but cannot stop timer in one of those tasks when…
Before this commit, when the project is private and the user can only access to some tasks inside that project, he can create timesheets but cannot stop timer in one of those tasks when `industry_fsm` module is installed. This commit makes sure the user can start/stop a timer on task for which he has access to even if the project is private and he does not have access to it. Steps to reproduce the issue: ---------------------------- 0. install industry_fsm module 1. Create a project A with "followers" as privacy visibility 2. Create a task A and assign it to a project user with lowest timesheet access right. 3. log in as that user 4. Start a timer on Task A 5. Stop the timer and confirm the wizard Expected Behavior: ----------------- The timesheet should be created without any issue Current Behavior: ---------------- An Access error is raised because the user has no access to the project. task-4680412 Forward-Port-Of: odoo/enterprise#91308 Forward-Port-Of: odoo/enterprise#84807
This fix corrects how absence-related days are calculated in Swiss payroll reporting. It helps ensure payroll figures and related submissions are more accurate, reducing the risk of incorrect employee or compliance data.
Original PR description
Forward-Port-Of: odoo/enterprise#91391 Forward-Port-Of: odoo/enterprise#91358
Vendor batch payments now use the correct payable account when matched with bank statement lines. This prevents reconciliation from posting to the wrong partner account and helps keep supplier balances accurate.
Original PR description
**Steps to reproduce:** - Install accountant - Go to "Accounting / Vendors / Payments" - Create a payment: * Payment Type: Send * Vendor: [any] * Amount: 1000 - Confirm the payment - From payments list, select the payment and create a batch - Validate the batch payment - From Accounting dashboard, go to Bank journal - Create a statement: * Partner: [None] * Amount: -1000 * Memo: [anything] - Reconcile the statement with the batch payment **Issue:** The receivable account of the partner is used for the batch line instead of his payable account. **Solution:** Select the type of the account to use depending on the type of the payment. opw-4952786 Forward-Port-Of: odoo/enterprise#91354 Forward-Port-Of: odoo/enterprise#91206
When sending a document for signature, users who are also listed as signers are now taken directly to their signing page instead of seeing a confusing prompt to send the document again. This makes the signing flow clearer and avoids repeated signer entry.
Original PR description
**Version:** - saas-18.3 **Steps to reproduce:** - Open a sign template. - Click "Send". - Add signers (include yourself). - Click "Send" to confirm. - The template is shown in preview mode. - Click "Sign Now". - A new "Send" dialog appears. - You have to add signers again. - Click "Send" again. **Issue:** - When the logged-in user is one of the signers, clicking the "Send" button shows a notification and not allows the user to sign. But clicking "Sign Now" again after that is confusing. **Solution:** - If the current user is a signer, clicking the "Send" button should directly open the sign view for that user to sign. task-4933608 Forward-Port-Of: odoo/enterprise#89943
Fixed an issue where all-day calendar events could incorrectly make valid evening appointment slots appear unavailable in some time zones. This improves booking accuracy for users scheduling appointments near midnight UTC.
Original PR description
All-day calendar events were incorrectly causing unavailability for appointment slots scheduled on the previous evening, due to mismatches between local time and UTC. Previously, all-day events…
All-day calendar events were incorrectly causing unavailability for appointment slots scheduled on the previous evening, due to mismatches between local time and UTC. Previously, all-day events scheduled for Tuesday were stored with a start time of 00:00 UTC. In timezones like America/Chicago, this corresponds to 7:00 PM Monday. As a result, a valid appointment booked from 6:30 PM to 8:00 PM local time on Monday would partially fall into Tuesday in UTC (ending at 01:00 UTC), causing a false conflict with Tuesday’s all-day event. The `calendar_verify_availability` method now calls the newly added `_get_date_boundaries` which than computes naive datetime boundaries based on the user's local timezone by taking the end of the previous local day and the start of the next local day. This change resolves those edge cases where evening slots crossing the UTC boundary were falsely marked as unavailable due to timezone misalignment. opw-4614544 Forward-Port-Of: odoo/enterprise#90680 Forward-Port-Of: odoo/enterprise#85654