Monday, October 13, 2025
4 changes · saas-18.2
Enhancements to existing features
Unpaid leave and unpaid sick leave days are now excluded from UAE end-of-service and provision salary calculations, making payroll results more accurate. End-of-service payslips also display the total unpaid leave days for clearer employee and HR review.
Original PR description
This commit excludes the Out Of Contract Unpaid Leaves and Unpaid Sick Leave days from the EoS and EoS Provision Salary Rule Calculations. We also show the total number of unpaid leave days on the EoS payslip. task-4886104 Forward-Port-Of: odoo/enterprise#95465
Paired IoT Boxes will now always connect to the database IoT communication channel, instead of checking whether that channel is marked open or closed. This makes the behavior easier to understand and helps teams troubleshoot connection issues more consistently.
Original PR description
In order to simplify debugging and UX, we removed the open/closed WebSocket logic for IoT Boxes. A paired IoT Box should always connect to the db IoT WebSocket channel. Forward-Port-Of: odoo/enterprise#96822
Resolved issues and error corrections
UrbanPiper POS orders now apply the correct taxes when a point of sale is set up under a branch company. This prevents undercharging or inaccurate tax reporting in multi-branch businesses, including cases where taxes are split into sub-taxes.
Original PR description
Steps to reproduce: --- - Install `pos_urban_piper`. - Create a branch under *Main Company*. - Switch to the new branch. - Create a POS config in this branch and set up UrbanPiper. - Sync "Apple Pie". - Place an order with "Apple Pie". Issue: --- - The 15% tax defined on Apple Pie is not applied on the orderline. Cause: --- - While creating the order line, the tax company was compared directly with the POS config’s company. In this case, the tax belongs to the parent company, while the POS config belongs to a child company. Fix: --- - Compare the `root_id` of both companies instead of the direct company ID to ensure taxes are applied correctly in multi-branch setups. - Additionally, handled the case where a main tax has sub-taxes (e.g., 5% GST split into 2.5% SGST and 2.5% CGST). In such cases, we now fetch the tax type from the sub-taxes instead of the main tax. Task-5050682 Forward-Port-Of: odoo/enterprise#93467
This fix prevents Field Service report cleanup logic from failing when related worksheet data has already been removed during module uninstallation. It helps avoid incomplete uninstallations that can later cause reinstall problems or database consistency issues.
Original PR description
Recently pull request https://github.com/odoo/enterprise/pull/86084 introduced an ondelete method on `ir.model` that retrieves some worksheet templates to delete them. However, this method breaks…
Recently pull request https://github.com/odoo/enterprise/pull/86084 introduced an ondelete method on `ir.model` that retrieves some worksheet templates to delete them. However, this method breaks when uninstalling module `worksheet`:
```
ir.model.data._module_data_uninstall():
... records are deleted ...
ir.model.fields.unlink():
drop column of corresponding fields
delete ir.model.field records
ir.model.unlink():
drop table of corresponding models
ir.model._unlink_if_uninstalling():
self.env['worksheet.template'].search([('model_id', ...)]).unlink()
delete ir.model records
```
The call to `ir.model.unlink()` crashes when searching for worksheet templates, since column `model_id` has been dropped already. This makes the transaction fail, and it is rolled back to a savepoint just before the call to `ir.model.unlink()`. In other words, the uninstallation manages to drop most of the columns that must go, but fails to drop all the tables that must go. And the uninstallation proceeds anyway...
Now consider uninstalling module `resource`. That module defines model `resource.calendar` with required field `name`, and also defines a record in that model (a default calendar). When the module is uninstalled, module `worksheet` is also uninstalled (because it depends on `resource`), and so the situation above happens. Consequently, most of the columns of table `resource_calendar` are dropped, but the table is not. If we reinstall module `resource` after that, the ORM re-creates column `name` (which is `NULL` on the default calendar at least), but fails to add the `NOT NULL` constraint on that column.
The fix consists in avoiding the `search()` above in the ondelete method if the column `model_id` does not exist anymore.
Forward-Port-Of: odoo/enterprise#96845