Monday, September 28, 2026
9 changes · saas-19.2
Resolved issues and error corrections
This fix keeps Odoo responsive when a Studio customization contains an invalid relationship setting. It prevents saving new invalid configurations and safely handles existing ones, so users can correct the field without triggering server errors.
Original PR description
### Current behavior: When a Studio custom One2many field has an invalid relation field (inverse) name, accessing `registry.field_inverses` raises KeyError. On 19.0 this also crashes error-page…
### Current behavior: When a Studio custom One2many field has an invalid relation field (inverse) name, accessing `registry.field_inverses` raises KeyError. On 19.0 this also crashes error-page rendering, leaving the server unusable after closing Studio. On 18.0, it doesn't crash the server. ### Expected behavior: An invalid inverse name must not crash the registry or error handler; the server should stay responsive so the user can fix the field. ### Steps to reproduce: 1. Install sales, project with demo data 2. Create a sale order, use Studio to add a new "Lines" field (e.g. test line) 3. In the sale order, add a product that has Create on Order field (e.g. plumbing services from the demo data) > Confirm 4. Click on the smart button to go to project/task 5. Switch to Studio again, add a related field in the task, point that to Sales Order > test line 6. Activate debug mode, click on More for test line (task) 7. In properties, turn off Read only. Important here: add an invalid key for Relation Field (e.g. 'hehe') 8. Error popup shows key error. Try to close and exit out of Studio mode > Server crashes with 500 Internal Server Error ### Cause of the issue: - When a custom One2many field has an invalid `inverse_name` (set via Studio developer mode), `One2many.setup_inverses` accessed `registry[comodel]._fields[inverse_name]` without checking existence - Building the cached `registry.field_inverses` property then raises an uncaught KeyError and bricks the server with 500 Internal Server Error ### Fix: - When a custom One2many field has an invalid inverse_name (set via Studio developer mode One2many.setup_inverses accessed registry[comodel]._fields[inverse_name] without checking existence - Building the cached registry.field_inverse property then raises an uncaught KeyError and bricks the server with 500 Internal Server Error opw-6479178 Forward-Port-Of: odoo/odoo#287589
The Belgian payroll time off calendar now correctly greys out days covered by Parental Time Off or Time Credit schedules. This helps employees and HR teams see unavailable days accurately and avoid confusion when reviewing leave calendars.
Original PR description
Issue: ---------------------------------------- When having calendar attendances with the "Parental Time Off" work entry type, then the time off calendar view doesn't show these days as greyed out…
Issue: ---------------------------------------- When having calendar attendances with the "Parental Time Off" work entry type, then the time off calendar view doesn't show these days as greyed out even though it should. Steps to reproduce: ---------------------------------------- - Install l10n_be_hr_payroll and be on a Belgian company - Have an employee with a contract - In the Payroll tab define a start date and an end date for the contract. - In "Working Hours", create a new working schedule where the Work Entry Type is either Parental Time Off (Belgium) or Time Credit for all five weekdays. - Click the "Time Off" smart button - The days covered by the contract aren't greyed out Cause: ---------------------------------------- `_work_intervals_batch` only subtracted the Parental Time Off/Credit Time attendances when `r and not r._is_flexible()`. `_get_unusual_days` never sets `resources_per_tz`, so `r` is always the empty placeholder resource, which is falsy, so the subtraction never ran. Solution: ---------------------------------------- Subtract unless `r` is an actual flexible resource, instead of only when it is a non-flexible one. Note: ---------------------------------------- Not reproducible as of saas-19.3: hr_work_entry's ResourceCalendar gained its own generic `_work_intervals_batch` override there that subtracts any attendance whose work entry type has `count_as == 'absence'`, with no flexible-resource guard. Parental Time Off/Credit Time already have `count_as == 'absence'`, so that override masks this bug by excluding them first. This fix is still needed to make the l10n_be-specific logic correct in its own right. opw-6397416
This fix prevents users from being shown a misleading “Pick From” option when splitting dropship operations that should only create new lots. As a result, the lot number and expiration date entered by the user are now correctly applied, reducing delivery errors for tracked products.
Original PR description
Steps to reproduce 1. In Inventory Settings, enable Lots & Serial Numbers and Expiration Dates. 2. Create a storable product tracked by lot with Expiration Date enabled. 3. Create and confirm a…
Steps to reproduce 1. In Inventory Settings, enable Lots & Serial Numbers and Expiration Dates. 2. Create a storable product tracked by lot with Expiration Date enabled. 3. Create and confirm a dropship of it, then open the move's Detailed Operations. 4. The pre-filled line works: typing a batch and an expiration date creates exactly that lot at validation. 5. To split the quantity, click "Add a line": it opens the "Pick From" popup, and choosing "Create" there creates the lot and attaches it to the line. 6. On that line, edit "Lot/Serial Number" and "Expiration Date", then Validate. -> Expected: the values entered on the line are used. -> Actual: they are ignored; the lot created through "Pick From" is delivered with its own expiration date, the name and date typed on the line have no effect. Issue --- On a create-lots-only non-incoming operation like `Dropship`, `show_quant` is derived from `picking_code` alone, so the "Pick From" quant picker is shown even though the operation only creates lots. Adding a line goes through "Pick From", which creates the lot and attaches its `lot_id` to the move line; from then on the line's `lot_name` and `expiration_date` stay editable but do nothing, since a set `lot_id` is used as-is at validation and the `expiration_date` is recomputed from the lot, so anything typed there is silently dropped. Such an operation has no existing stock to pick from, so `show_quant` is now gated on the lot settings too: "Pick From" is hidden and the line's `lot_name` and `expiration_date` become the only inputs, created into the lot at validation like receipts already do. https://github.com/odoo/odoo/blob/68dcb950df83d70ff2aea0e05c96cc9b57c1a8a9/addons/stock/models/stock_move.py#L646-L647 opw-6530563 Forward-Port-Of: odoo/odoo#290071 Forward-Port-Of: odoo/odoo#287474
Fixed an issue in Discuss where a new message could disappear temporarily if it arrived while a channel was still loading. Users now see incoming messages reliably without needing to wait for another refresh or fetch.
Original PR description
Before this commit, a message received while a channel opens in Discuss does not appear, and stays out of the thread until the next fetch. This happens because the channel opens on its last read message through `loadAround`, which replaces the message list with the fetched messages. The bus handler of a new message adds it to that list as long as the thread displays the present, so the replacement drops what arrived during the fetch. This commit fixes the issue by putting those messages back: in the list when it displays the present, in `pendingNewMessages` when it does not, where `fetchMoreMessages` already picks them up. https://runbot.odoo.com/odoo/error/947188 Forward-Port-Of: odoo/odoo#290388 Forward-Port-Of: odoo/odoo#289976
This fixes an error that prevented users from being added to payroll groups from the Groups screen in Australian Payroll API databases. It also ensures both additions and removals are properly audit-logged, improving reliability and compliance tracking without changing existing workflows.
Original PR description
#### Description of the issue/feature this PR addresses:
Adding a user to a group from the Groups form crashes on an Australian Payroll-API database, and removals from that form are never audit-logged.
#### Current behavior before PR:
The audit-logging mixin reads the changed users out of the raw write command with vals.get("user_ids")[0][2], which assumes a 3-element command tuple. The Groups form sends the 2-element (4, id) LINK command, so the write raises an IndexError; UNLINK commands are silently not logged for the same reason.
#### Desired behavior after PR is merged:
Group membership changes made from the Groups form are audit-logged for both additions and removals, regardless of the command used to write user_ids. The mixin reads the members before and after the write instead of interpreting the command. No field, model or method-signature change, so it is safe in stable.
opw-6397011
Forward-Port-Of: odoo/enterprise#132821
Forward-Port-Of: odoo/enterprise#125124Users can now click ticket analysis charts or pivot cells grouped by employee, manager, or department without hitting a server error. The report now correctly opens the related helpdesk tickets, making timesheet and support reporting more reliable.
Original PR description
Currently, an error occurs on clicking on the graph or the pivot cell if the data is grouped by Employee/Manager/Department. ### **Steps to reproduce** 1) Install helpdesk_timesheet with demo data 2)…
Currently, an error occurs on clicking on the graph or the pivot cell if the data is grouped by Employee/Manager/Department.
### **Steps to reproduce**
1) Install helpdesk_timesheet with demo data
2) Go to Timesheet > Reporting > Ticket Analysis
3) Set group by to Employee
4) Click on any graph bar or pivot cell
### **Error:**
`ValueError: Invalid field helpdesk.ticket.employee_id in condition ('employee_id', '=', 1)`
Root Cause:
The `helpdesk.ticket.report.analysis` model includes specific fields such as `employee_id`, `department_id`, and `employee_parent_id` (see [1]) that are defined for reporting purposes but do not exist on the `helpdesk.ticket` model. When a user clicks a data point to view related tickets, the reporting view passes the current domain directly to the ticket list view. Because `helpdesk.ticket` lacks these fields, the ORM fails to validate the domain, resulting in a server error.
[1]- https://github.com/odoo/enterprise/blob/8d16b647431985dd7c216ae39eea6ca050e04b46/helpdesk_timesheet/report/helpdesk_ticket_report_analysis.py#L15-L17
### **Fix:**
This commit introduces a mixin to intercept the openView call. The mixin maps reporting-specific fields to valid relational paths on the ticket model `(for example, employee_id is transformed into user_id.employee_id)`. This ensures that the domain generated from the report model is compatible with the target ticket model.
**opw-5931273**
Forward-Port-Of: odoo/enterprise#108503Kenya eTIMS submissions now exclude taxes that do not have a KRA tax code from the reported tax-inclusive total. This prevents levies owed to other authorities, such as tourism levies, from being incorrectly reported to the Kenya Revenue Authority.
Original PR description
Issue: Non KRA taxes are sent in eTIMS tax total Steps to reproduce: - With l10n_ke_edi_oscu - Create a 2% Tax named CTL with no KRA Tax Code - Create an invoice - Add a line with 16% and CTL taxes - Confirm - Send to eTIMS Current behavior: - eTIMS JSON (unaccessible) is created with 'totAmt' (total_tax_included) including non-KRA Taxes Expected Behavior! - eTIMS JSON 'totAmt' doesn't incldue non-KRA Taxes Note: eTIMS is used to report to Tax Autority, however some "taxes" (e.g. Tourism levy) are paid to other authorities (e.g. Tourism Fund) and shouldn't be included in eTIMS. opw-6456478 Forward-Port-Of: odoo/enterprise#131577
This fix updates formulas used in the Swiss balance sheet report so figures are calculated and presented correctly. It helps Swiss accounting users rely on more accurate financial statements for review and reporting.
Original PR description
Change some formulas in the Swiss balance sheet task-6379692 Forward-Port-Of: odoo/enterprise#123895
Italian invoices using the Import/Export fiscal position now apply the correct single 0% tax instead of adding two overlapping 0% taxes by default. This prevents incorrect tax setup on invoice lines and helps businesses avoid manual corrections and potential reporting errors.
Original PR description
Upon Import/Export, the 0% EX N7 tax is added by default on each tax excluded line, as it incorrectly shares the same default Import/Export fiscal position with the standard 0% EX tax. This causes both to be applied simultaneously to a single invoice line. 1. Install Accounting and `l10n_it` 2. Switch to IT company 3. Go to Invoices and create a new one 4. Select the Import/Export fiscal position 5. Add a line with a new product (so it's clean of custom product taxes) 6. Both `0% EX` and `0% EX N7` taxes are applied, instead of just `0% EX` Ticket [link](https://www.odoo.com/odoo/project.task/6518926) opw-6518926 Forward-Port-Of: odoo/odoo#285586