Daily updates from Odoo
Thursday, August 20, 2026
30 changes · master
Enhancements to existing features
Point of Sale configurations now load the required products for due-payment settlement and UrbanPiper delivery integration more reliably. This helps ensure the right products are available when POS sessions are created or loaded, reducing setup friction and operational errors.
Original PR description
*=pos_urban_piper Following this commit: ==== - Load pos_settle_due products when creating or loading a POS config. - Load urbanPiper products when at least one configuration has urbanPiper enabled task-6171250 Related PR : https://github.com/odoo/odoo/pull/262669
Saudi payroll now splits sick leave at the time leave is created, instead of waiting until payslip calculation. This makes leave handling more consistent across countries and improves payroll accuracy by using standardized work-day calculations and rate-based unpaid entries.
Original PR description
Purpose: move the logic of handling SA sick leave split from payslip computation to automatic split during leave creation - refactored the sick leave split logic from `l10n_be_hr_payroll` and `l10n_lu_hr_payroll` to a standardized logic in `hr_holidays` with the ability to split leaves using calendar days or worked days - added the logic for SA sick leave split during leave creation - changed hardcoded unpaid work entries to use amount rate - adapted the use of the method `_number_of_workdays` to use standard `_get_work_days_data_batch` task-id: 6379346
Brazilian shipments sent through Envia.com can now include the required NF-e access key, helping carriers receive the fiscal information they need. The system automatically looks for the linked invoice from packages, pickings, or the sale order, and if none is ready it lets the warehouse validation finish while prompting the user to link and validate an invoice before sending to the shipper.
Original PR description
In Brazil, if you are using Envia.com or other delivery providers you need to make sure you are sending the NF-e Access Key on shipment generation to make sure that the freight company has the right data. In the normal flow: Sale Order -> Invoice -> Picking, the related invoice is automatically attached to the picking so the customer doesn't have to do anything. Priority is invoice on individual package, invoice attached to the picking, invoice attached to the sale order as a final fallback. If all three are missing and not sent to the government yet, the picking will validate fully, but not automatically send to Envia.com. It will instead post to the chatter that an invoice needs to be validated and linked properly to the record before hitting Send to Shipper. task-6120965
Updating a company’s return reminder day now recalculates deadlines only for open account returns that are affected. This preserves the same business behavior while reducing unnecessary processing as the number of returns grows.
Original PR description
In this commit: - Remove the 'company_id.account_return_reminder_day' dependency from the '_compute_deadline' compute method. - Avoid triggering the compute method for all related account returns whenever 'account_return_reminder_day' is updated, as this becomes increasingly expensive when the number of records grows. - Override 'res.company.write()' to detect changes to 'account_return_reminder_day'. - Manually trigger '_compute_deadline()' only for non-completed account returns that are actually affected by the change, reducing unnecessary recomputations while preserving the existing behavior. task-[6296822](https://www.odoo.com/odoo/project/967/tasks/6296822)
Odoo now checks whether a payment or batch payment exceeds the maximum amount allowed by the connected financial institution before initiating it. This helps prevent failed payment attempts and gives users earlier feedback when a bank-imposed limit applies.
Original PR description
Before trying to initiate payments through Odoo/Odoofin, we should check that the total amount for the (batch) payment does not exceed the maximum payment amount allowed by the institution (some Powens institutions introduced that limit). task-6310729 Forward-Port-Of: odoo/enterprise#127110 Forward-Port-Of: odoo/enterprise#121513
Cash journal users can now choose an account directly when quickly creating bank statement lines, reducing extra reconciliation steps. The update also strengthens cash statement posting and deletion rules so records stay consistent and compliant when journals are secured.
Original PR description
This commit will add the possibility to add an account on the quick create view of a bank statement line when being on a cash journal that when selected will do a set account on the statement line created with the account selected no task id
Payroll will no longer automatically set the current driver of a company car based on benefits alone. Instead, employees are marked as future drivers when they choose or receive a car, preventing already reserved cars from being offered again and reducing unnecessary administrative tasks.
Original PR description
. Remove the auto-assignment of the Driver based on the payroll benefits. . If an employee signs a contract and selects the car or the car gets added to the employee's benefits, he should become the car's future driver. . Don't offer in the salary configurator cars for which the future driver is filled. . Don't generate a task every time the payroll officer assigns a new driver to the car . Add the corresponding tests task-6425360 Forward-Port-Of: odoo/enterprise#127390 Forward-Port-Of: odoo/enterprise#126016
Bulgarian companies can now have required monthly VAT reporting files generated automatically when validating a VAT return. The change adds the General Ledger SAF-T file plus purchase and sales reports to the return attachments, reducing manual work and helping with local compliance.
Original PR description
Bulgaria made it mandatory for large companies to present a monthly file
to report their VAT to the administration. To streamline that process,
when the VAT return is validated and PDF is added to the attachments,
the monthly General Ledger SAF-T file, the POKUPKI Purchase Report and
PRODAGBI Sale Report are produced and added as well.
Simplify the report file download error wizard's visuals and descriptions to improve readability.
task-6007963
Forward-Port-Of: odoo/enterprise#127736
Forward-Port-Of: odoo/enterprise#118326Budget report loading has been optimized to avoid inefficient record matching that could make reports unusably slow on larger databases. This should significantly reduce wait times for users opening budget reports, especially when many analytic lines and budget lines are involved.
Original PR description
**Description:** While loading the budget report, the bad queries are created by ```def _get_aal_query()``` and ```def _get_pol_query()``` function, makes the budget report unusable. **Root cause:**…
**Description:**
While loading the budget report, the bad queries are created by
```def _get_aal_query()``` and ```def _get_pol_query()``` function, makes
the budget report unusable.
**Root cause:**
Instead of doing a hash join while searching the record,
the OR statement in the Left Join in the condition
```(%(bl)s IS NULL OR %(a)s = %(bl)s)```
creates a nested for loop that compares everything single aal to bl,
this causes a significant performance issue as the number of the
number of check will be the the number aal * bl,
if a database has a 70k aal and 20k bl, both numbers are not large
but it will cause a 70k * 20k search which is more than a billion.
**Fix**:
There are some refactors made in this PR.
_First_, separate out the Q1.
In order to find the aal that has no bl connects to it.
Doing a search to find the aals that have bl and then subtract them from all aals.
_Second_, Instead of doing a nested loop for by using
```(%(bl)s IS NULL OR %(a)s = %(bl)s)```,
originally we will have do something like
```
JOIN budget_line bl
ON (bl.x_plan2_id IS NULL OR aal.x_plan2_id = bl.x_plan2_id)
AND (bl.x_plan3_id IS NULL OR aal.x_plan3_id = bl.x_plan3_id)
AND (bl.x_plan4_id IS NULL OR aal.x_plan4_id = bl.x_plan4_id)
```
Assuming each bl has three plans ```x_plan2_id```, ```x_plan3_id```, ```x_plan4_id```
Grouping the bl base on whether a specific plan is set, (i.e. shapes)
we can skip the ```IS NULL OR``` because we already know which plan
is null and do the hash join directly.
For example, the shapes will be a dictionary with a key of a tuple of booleans
based on whether a plan is set or not and the value is a list of bl_id.
```
{
(True, False, False): [1, 2],
(False, True, True): [3, 4],
(False, False, False): [5],
}
```
we can end up doing something like
```
JOIN budget_line bl
ON bl.id = ANY(ARRAY[3,4])
AND aal.x_plan3_id = bl.x_plan3_id AND aal.x_plan4_id = bl.x_plan4_id
```
which is way more faster.
---
The benchmark is made locally from this client's database which contains
69k aal, 23k bl, 6829 pol and 3 plans for aal and bl.
|Record count |Time before|Time after|
|--------------------------------------------------|-----------------|---------------|
|69k aal, 23k bl, 6829 pol, 3 plans |70.04s |4.6s |
Dalibo:
Before:
Month-over-month grand total by company:
https://explain.dalibo.com/plan/8h3d4e89aaf9f3d4
Overall grand total by company:
https://explain.dalibo.com/plan/445g1f9caf4923e2
Month-over-month grand total by plan:
https://explain.dalibo.com/plan/53a138ca50b2a7c4
Overall grand total by plan:
https://explain.dalibo.com/plan/hdbe169ddc7g5785
After:
Month-over-month grand total by company:
https://explain.dalibo.com/plan/hcc86c801e6872bf
Overall grand total by company:
https://explain.dalibo.com/plan/69b2421a3581f98h
Month-over-month grand total by plan:
https://explain.dalibo.com/plan/a88f398bbbch3148
Overall grand total by plan:
https://explain.dalibo.com/plan/1gg749ae7ab1553c
opw-6345552
Forward-Port-Of: odoo/enterprise#127732
Forward-Port-Of: odoo/enterprise#124161Shopfloor work orders now handle quantity updates consistently with the backend for continuous production, avoiding unintended changes to the quantity being produced. The work order form layout was also reorganized to make continuous production information clearer for users.
Original PR description
In this commit, shopfloor is modified in order to match the behaviour in the backend; On updating WO's quantity, the quantity producing is not updated if its a continuous production. Workorder form fields were also re-ordered as a part of the ongoing continuous production clean. Task: 6346515 Forward-Port-Of: odoo/enterprise#123215
Payroll warning checks are now grouped so the system avoids repeating the same lookup many times. This should make payslip and employee payroll version processing faster when many warnings are active, without changing the warnings users see.
Kitchen staff can now print preparation tickets on demand directly from the kitchen workflow. Tickets can also print automatically when orders reach configured stages, and added barcodes let staff scan tickets to move orders forward faster.
Original PR description
*: pos_restaurant_preparation_display, pos_urban_piper, pos_self_order_preparation_display In this commit: ------------------- - Introduced functionality to print KOTs on demand from the kitchen. - Added support for automatic printing when an order is moved to a configured stage. - Added barcodes to KOTs printed from the kitchen, allowing kitchen staff to scan them and directly move the order to the next stage. task: 6131467 Related PR: https://github.com/odoo/odoo/pull/273944
Sign managers and the person who sent a signature request can now add or change the linked record at any stage. This helps teams correct or complete request details after the request has moved beyond the sent state, while keeping the field read-only for other users.
Original PR description
Before: - The 'Linked To' field on a Signature Request could only be edited while the request was sent state After: - Sign manager and user who sent SR can now set or change the "Linked To" field at any time. - Other users keep seeing the field as read-only. Impact: - Admins and request senders can correct or add the linked record even after the request has moved past the sent state. Taskid: 6321326
This update refreshes the spreadsheet interface to align with the latest underlying spreadsheet library. Users will see more consistent icons, section styling, and drag-and-drop behavior when working with lists, pivots, and filters in spreadsheet side panels.
The Mexico e-invoicing website sale flow was updated to stay aligned with recent community changes. This helps keep online checkout invoicing behavior consistent and reduces the risk of issues for Mexican localization users.
Original PR description
community PR: https://github.com/odoo/odoo/pull/278561
Resolved issues and error corrections
Project Forecast no longer shows the Time Management section in project settings when the Timesheets app is not installed. This prevents users from seeing irrelevant settings and keeps project configuration aligned with installed apps.
Original PR description
**Steps to reproduce:** - Install the project_forecast module. - Go to Projects -> Open the settings of any project (create one if none exist) -> Settings. - You will see the Time Management section. **Issue:** The project_forecast module was forcefully setting the invisible attribute of group_time_managment to 0. This caused the group to remain visible at all times, even when the Timesheets app was not installed. **Fix:** Remove the forced attribute setting from the project_project_view. The visibility is already properly managed by the hr_timesheet module, and project_forecast does not depend on timesheet_grid or hr_timesheet. task-6195716 Forward-Port-Of: odoo/enterprise#128350 Forward-Port-Of: odoo/enterprise#121454
An automated accounting test was adjusted to match a related platform fix in how grouped data handles file-size information. This keeps the test suite aligned with the corrected behavior and helps prevent false failures during future updates.
Original PR description
The fix at https://github.com/odoo/odoo/pull/281911 adds bin_size: tru in the web_read_group. This commit adpats an accounting test as a consequence Forward-Port-Of: odoo/enterprise#128089 Forward-Port-Of: odoo/enterprise#127638
Correcting a paid payslip now creates the related payroll batch under the same company as the payslip, instead of defaulting to the user's currently active company. This prevents payroll correction batches from mixing companies and helps keep multi-company payroll records accurate.
Original PR description
Steps to reproduce: - Have an employee in company B, with a paid payslip - Log in with company A active (company B allowed but not selected) - Open the employee's paid payslip and click "Correct" The refund and correction payslips are computed in company B (their company follows the employee), but the pay run created for them by the wizard has no explicit company and falls back to the active company A. Set the pay run's company from the payslips it contains, and group the payslips by company as well as by structure so that a batch never mixes companies. task-6428755 Forward-Port-Of: odoo/enterprise#126064
International shipments using Sendcloud DPD can now include the required customer tax details in customs information. This prevents validation errors when shipping to customers with VAT numbers and adds safer fallback values for required customs fields.
Original PR description
### This is a revision of #119399 which had to be reverted. Original issue ----- Deliveries cannot be validated using DPD with Sendcloud, users get an error. Steps to reproduce ----- - Set up…
### This is a revision of #119399 which had to be reverted. Original issue ----- Deliveries cannot be validated using DPD with Sendcloud, users get an error. Steps to reproduce ----- - Set up Sendcloud DPD - Create a SO - Interntional customer - Some VAT number - Some product - Add sendcloud delivery - Confirm SO - Validate the linked picking > Error: “The receiver VAT number is missing; please provide it to continue” Issue's cause ----- Tax numbers should be included in the `customs_information` field of the request as per the API https://sendcloud.dev/api/v2/parcels/create-a-parcel-or-parcels#body-one-of-0-parcel-customs-information-tax-numbers For the `vat_label` field, we have to force the language to English in the context because the field is translated by default, but sendcloud only accepts the english names (eg French "TVA" is not accepted, expected value is "VAT"). https://github.com/odoo/odoo/blob/d1d1610332a1596d026fb0a42ec236d1a79c71cc/odoo/addons/base/models/res_country.py#L75 Revert cause ----- The vat_label field is marked for translation (translate=True) https://github.com/odoo/odoo/blob/d1d1610332a1596d026fb0a42ec236d1a79c71cc/odoo/addons/base/models/res_country.py#L75 So if the user has the DB in french for example, we are sending "TVA" instead of "VAT" in the name field. Other issues ----- - We need to provide an actual fallback for `customs_invoice_nr`. As it stands, if we create a new delivery it cannot be validated because Sendcloud doesn't accept for the field to be empty. - Same for `name`, we need to provide an actual fallback. ----- Ticket: opw-6250860 Forward-Port-Of: odoo/enterprise#127425 Forward-Port-Of: odoo/enterprise#124245
The payment registration flow now uses the bank account selected in the payment wizard when no bank account is set on the invoice entry. This prevents the “Pay Now” button from disappearing in valid payment scenarios, making online payment initiation more reliable for users.
Original PR description
Before this commit, it could happens that when we don't put a partner_bank_id on the move it self. The "pay now" button was never displayed. It was because partner_bank_ids was only checking the value from the move and not the wizard. Now if there is no partner_bank_id in the wizard.batches then we look at the value in the wizard and we use it. task-6374002 Forward-Port-Of: odoo/enterprise#123759
Completed point-of-sale kitchen orders are now removed from the customer-facing order status display instead of showing again as "Almost There." This keeps the status screen accurate for customers and staff once an order has finished preparation.
Original PR description
Steps to reproduce ------------------ - Open a PoS session, the Kitchen Display, and the Order Status Display. - Create an order and send it to the Kitchen. - Process the order through all the stages until it reaches the final (completed) stage. Issue ----- - Once the order reaches the completed stage, it reappears in the "Almost There" section of the Order Status Display instead of being removed. Cause ----- - The applied domain fetched all kitchen orders, including completed ones. The display logic only distinguishes whether an order is in the second last preparation stage than show it as "Ready", all other orders are shown as "Almost There". As a result, completed orders fall back into the "Almost There" section.. Fix --- - Updated the domain to fetch only active kitchen orders and exclude completed ones from the Order Status Display. Task: 6394865 Forward-Port-Of: odoo/enterprise#124947
The Point of Sale Urban Piper ticket screen now shows the order information button on mobile as well as desktop. This ensures staff using phones or smaller devices can access the same order details without switching views or devices.
Original PR description
Before this commit: ------------ - The order info button was not visible on the ticket screen in the mobile UI. After this commit: ------------ - Display the order info button in both the mobile and desktop views of the ticket screen. Related: - Community: https://github.com/odoo/odoo/pull/276568 Task-6388045 Forward-Port-Of: odoo/enterprise#127785 Forward-Port-Of: odoo/enterprise#124485
The Timesheet Assistant now gives a clearer suggestion when it detects time spent in the Discuss inbox. Instead of an awkward discussion-related label, users will see “Checking Inbox,” making timesheet suggestions easier to understand and use.
Original PR description
## Previous Behavior When the Timesheet Assistant detected a user spending time in their Discuss inbox, it generated a suggestion labeled "Discussing in/with Inbox". The name of this suggestion was judged to not make much sense. ## New Expected Behavior When the Timesheet Assistant detects a user spending time in their Discuss inbox, it will now generate a suggestion labeled "Checking Inbox" due to a new assistant rule. task-[6420655](https://www.odoo.com/odoo/project/4105/tasks/6420655) Forward-Port-Of: odoo/enterprise#127901 Forward-Port-Of: odoo/enterprise#126328
Live Chat sessions using an AI agent now send the correct agent identifier when starting a chat. This prevents errors that blocked guest users or website visitors from opening the chat window, improving access to automated support.
Original PR description
When configuring an AI agent in Live Chat and opening it as a guest user or from website > chat bubble, user is unable to open the chat window from the chat bubble and get a traceback instead. Currently, In `LivechatChannelRule` the `ai_agent_id` is declared as a relational field , so its value is a model record instead of an id. To fix this pass `ai_agent_id.id` when building the livechat session parameters to avoid serializing the model and causing a circular JSON error. task-6479187
A small typo was corrected in the Belgian payroll meal voucher report logic. This helps keep payroll reporting code clear and reduces the risk of confusion during future maintenance, with no expected change to day-to-day user workflows.
The timesheet menu has been adjusted to display more cleanly on mobile devices. This makes it easier for users to review or enter timesheets from smaller screens without a clunky interface.
Original PR description
In this commit, we improve the display of the timesheet systray in mobile view as it was clunky. task-6332208 Forward-Port-Of: odoo/enterprise#127829 Forward-Port-Of: odoo/enterprise#122491
Updates field service planning so completion actions appear in the right place depending on the view, reducing confusion for users. The onboarding tour now matches the updated scheduling workflow, and signing in from the Gantt popover refreshes the view so users can continue their work smoothly.
Original PR description
## [FIX] planning_field_service: display complete button in popover footer Before this commit, the complete button is displayed in the card even in the gantt popover instead of displaying it in the…
## [FIX] planning_field_service: display complete button in popover footer Before this commit, the complete button is displayed in the card even in the gantt popover instead of displaying it in the footer of the gantt popover. This commit makes sure the complete button in the card is only displayed in the kanban view and that button is displayed in the footer of the gantt view. ## [FIX] planning_field_service: adapt onboarding tour based on recent changes Before this commit, the quick create on resource_ids field in planning.slot has been replaced by a form view inside a modal. The Sign in button in gantt/calendar popover no longer automatically redirects the user to the form view of the intervention and so the user cannot directly complete the shift. This commit adapts the onboarding tour based on the recent changes. It also forces a reload in the gantt view when the user signs in a intervention via the Sign in button in the gantt popover. runbot-error-941063 task-[6353582](https://www.odoo.com/odoo/project/4105/tasks/6353582) Forward-Port-Of: odoo/enterprise#122495
This fixes cases where the Documents app on mobile could show an enabled Info & Tags button while the details panel was hidden or inaccessible. Users should have a more reliable experience when selecting files, switching views, reloading, or returning from previews.
Original PR description
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not…
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not displayed but the button is still enabled - Switching to the list view properly shows it **Issue:** Original fix (see [1]) was not enough for every case. Additional issues: - Chatter hidden on init even when its panel has `visible = true` - State desynchronized with the view when switching menu type (kanban/list) or by previewing a document and coming back - When using the button with an open preview, chatter shows up in the background but is not accessible (and going back discards it) - Removing selection with an open chatter disable the related action **Fix:** - Disable the chatter on mobile init by default to avoid having to manually move it back - Reset chatter on selection removal to avoid getting stuck in the menu - Reset chatter on view switch to avoid being in the wrong state afterwards (and revert the previous css changes) Not a great fix (quite mobile-specific) and there might still be some edge cases. [1] original fix: https://github.com/odoo/enterprise/commit/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52 opw-6061993 Forward-Port-Of: odoo/enterprise#127874 Forward-Port-Of: odoo/enterprise#121521
Fixes an issue where task or ticket timers could stutter, switch between different elapsed times, or show negative values after repeated stop/start and page reload actions. This improves reliability of time tracking for users working with timesheet timers, such as Field Service tasks.
Original PR description
A running task/ticket timer can sometimes stutter, show negative values, and track the wrong elapsed time. ### Steps to reproduce On a record with a timesheet timer (for example, a Field Service…
A running task/ticket timer can sometimes stutter, show negative values, and track the wrong elapsed time. ### Steps to reproduce On a record with a timesheet timer (for example, a Field Service task): 1. Start the timer and let it run for about 15-20 seconds. 2. Stop it and confirm the dialog. 3. Start it again. This creates a new `timer_start`. 4. Reload the page. The timer starts jumping every second between two different values. As it keeps running, it can even show negative values such as `00:00:-57`. If the problem does not appear right away, repeat steps 2-4 a few times. It usually shows up after a few stop/start/reload cycles. ### Cause The timer shown in the button bar is the `timer_start_field` widget. It starts a `setInterval` that updates a shared `TimerReactive` object once per second. While a form is loading, Odoo renders it several times in a row (for example: a first render, another when the chatter is loaded, and another when the record data comes back from the server). Rendering a form builds all of its fields to produce the display, so each of these renders creates its own `timer_start_field`. Odoo keeps and mounts only the render that ends up on screen; the earlier ones are thrown away before being mounted. The interval is started while the field renders, from the record observer set up in `setup`, before the field is mounted. So the fields that are later thrown away also start an interval. Those intervals keep running for the rest of the session. Each one updates the same shared `TimerReactive` object using the `timer_start` it was created with. As long as every instance has the same `timer_start`, they all write the same value and the problem stays hidden. After the timer is stopped and started again, the old instances keep the old `timer_start` while the mounted one uses the new one. Every second they overwrite each other's value, so the timer jumps between two different elapsed times. When the instance with the newer `timer_start` writes right after one with an older start, it tries to show a smaller elapsed time than what is already there, and the subtraction in `TimerReactive` produces a negative number of seconds. ### Fix Move the per-second timer update into a `useEffect`. The effect only runs after the field is mounted, and Owl automatically cleans it up when the field is unmounted or when `timer_start` or `timer_pause` change. This means fields that are destroyed before they are mounted never start an interval, so only the mounted field updates the shared timer. `onRecordChange` no longer starts or stops the interval. It only updates the displayed timer value to match the current record. opw-6209405 Forward-Port-Of: odoo/enterprise#128151 Forward-Port-Of: odoo/enterprise#126242
Code cleanup and technical improvements
This update removes a duplicate internal way of referring to the active point-of-sale order and uses one standard method instead. It should not change cashier workflows, but it makes the POS code easier to maintain across localization, stock, and IoT features.
Original PR description
..., pos_stock, l10n_sa_edi_pos, l10n_at_pos, l10n_mx_edi_pos, pos_iot --- `PosStore.selectedOrder` was just an alias for `getOrder()`. Use `getOrder()` directly everywhere and drop the getter. --- Task: https://www.odoo.com/odoo/project/1737/tasks/6468321