Sunday, August 23, 2026
12 changes · saas-19.3
Resolved issues and error corrections
This fixes an issue where converting certain decimal hour values into times could fail when the minutes rounded up to 60. The change correctly rolls those minutes into the next hour, preventing errors in calculations such as aggregated work hours while preserving normal behavior.
Original PR description
### Bug `odoo.tools.date_utils.float_to_time` builds the minutes with a rounding step: ```python return time(int(integral), int(float_round(60 * fractional, precision_digits=0)), 0) ``` When the…
### Bug
`odoo.tools.date_utils.float_to_time` builds the minutes with a rounding step:
```python
return time(int(integral), int(float_round(60 * fractional, precision_digits=0)), 0)
```
When the fractional part of the hour is high enough, `round(60 * fractional)`
rounds up to a full **60**, and `time(hour, 60)` is invalid:
```python
>>> float_to_time(16.9959)
ValueError: minute must be in 0..59, not 60
>>> float_to_time(8.999)
ValueError: minute must be in 0..59, not 60
```
Any hours value whose fractional part is ≥ ~0.9917 hits this — which happens
easily with computed/aggregated work-hour floats.
### Fix
Carry the rounded-up minute into the hour, and return `time.max` when that carry
reaches the end of the day (mirroring the existing `hours == 24.0` case):
```python
if minute == 60:
hour += 1
minute = 0
if hour >= 24:
return time.max
```
`float_to_time(16.9959)` now returns `time(17, 0)`, `float_to_time(23.9959)`
returns `time.max`, and regular values are unchanged.
Adds `TestFloatToTime` in `test_date_utils.py` covering the carry, the
end-of-day carry, and regular values.
Forward-Port-Of: odoo/odoo#280807Refunded down payments made through Point of Sale are now handled correctly when a sale order is later settled or invoiced. This prevents customers from being invoiced for the refunded down payment amount again and keeps invoiced totals accurate.
Original PR description
The following commit resets qty_invoiced to zero on sale order lines paid by a POS order when that order is refunded. https://github.com/odoo/odoo/commit/ac39aa4f68dfc77011c39e468e3f60e0338a3c69…
The following commit resets qty_invoiced to zero on sale order lines paid by a POS order when that order is refunded. https://github.com/odoo/odoo/commit/ac39aa4f68dfc77011c39e468e3f60e0338a3c69 However, it does not handle the sale order line created for a refunded POS down payment. That line keeps `qty_invoiced` = -1, which causes the refunded amount to be included again when settling or invoicing the sale order. Steps to reproduce: - Create a sale order. - Pay a down payment through the POS. - Refund the down payment order from the POS. - Settle the remaining amount from the POS or invoice the sale order from the backend. Result: - The generated invoice includes the sale order total plus the refunded down payment. - Sale order `amount_invoiced` will be the down payment amount. Fix: - Delete the refunded downpayment to match the sale flow. - Include refunded down payments in the amount_invoiced computation. opw-6378891 Forward-Port-Of: odoo/odoo#283308 Forward-Port-Of: odoo/odoo#278011
This fixes an attendance calculation issue where a shift ending exactly at midnight could be counted again on the next day. Overtime is now recalculated using the correct day's attendance records, helping prevent incorrect overtime balances for employees.
Original PR description
When recomputing overtime, attendances overlapping the affected day are retrieved based on their check-in and check-out. An attendance whose check-out is exactly at the start of the following day is…
When recomputing overtime, attendances overlapping the affected day are retrieved based on their check-in and check-out.
An attendance whose check-out is exactly at the start of the following day is currently considered to overlap that day because the domain uses an inclusive lower bound on `check_out`.
This can cause overtime from the previous day to be recomputed using an incomplete set of attendances.
### Steps to reproduce:
* Configure an employee with a daily quantity overtime rule based on the expected hours from the contract.
* On the first day, create multiple attendances, with the last one ending exactly at midnight.
* Ensure the total worked hours on that day result in overtime.
* On the following day, create another attendance.
* Observe that recomputing the second day's overtime also retrieves the attendance ending at midnight.
* The previous day's overtime is then recomputed without the other attendances from that day, resulting in an incorrect overtime value.
* Regenerating the overtime ruleset restores the correct value.
For example, with 8.4 expected hours:
```
Day 1:
09:30 - 11:30
14:30 - 18:19
21:00 - 00:00
Day 2:
create/update an attendance
```
The `21:00 - 00:00` attendance is incorrectly included in Day 2's recomputation because its check-out equals the start of Day 2. The other Day 1 attendances are not included, so Day 1 is recomputed from only 3 hours of work.
To fix the issue we treat `check_out` as an exclusive interval boundary when determining overlap. An attendance ending exactly at the start of a day does not overlap that day, while attendances actually crossing midnight continue to be included.
opw-5474120
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#283894
Forward-Port-Of: odoo/odoo#283226Mentioning a partner linked to multiple active users in a discussion sub-channel no longer causes an error. The system now checks each user’s notification preference and invites the partner when at least one linked user allows channel notifications, keeping collaboration flows uninterrupted.
Original PR description
Before this commit, mentioning a partner that has two active users in a sub-channel ended on: ValueError: Expected singleton: res.users.settings(77, 80) This happens because the channel notification setting is read through res_users_settings_id, a Many2one on res.users, so two users give two settings records and reading a value on them asks for a singleton. Only an administrator reaches it, as the res.users.settings rule limits everyone else to their own settings. This commit fixes the issue by inviting the partner as soon as one of its users did not turn channel notifications off. Forward-Port-Of: odoo/odoo#283912 Forward-Port-Of: odoo/odoo#283805
Fixed a crash that could occur when users reopened the note composer and pressed Escape or arrow keys in the “Continue with Full Composer?” popup. These keys now do nothing in that context, keeping the chatter workflow stable and preventing an unnecessary error screen.
Original PR description
Reproduction steps: - Open a record that has a chatter where you can log notes - Start logging a note in the composer - Close the composer - Click log note again - See "Continue with Full Composer?" popup - Hit escape, up, or down - See traceback This shouldnt really do anything, so this fix makes it do nothing instead of crashing. opw-6476660 Forward-Port-Of: odoo/odoo#283389 Forward-Port-Of: odoo/odoo#282803
This fixes invoice tax calculations when one tax increases the base amount used by a following tax on the same line. The tax details now carry the first tax amount into the second tax totals, helping ensure invoice amounts and reports are accurate.
Original PR description
**Steps to reproduce:** - Create a tax that affects the base of the subsequent ones - Create an invoice with this tax and another one on the same line **Issue:** In "_aggregate_base_line_tax_details", the tax amount from the first tax should be included in the following values of the second tax: - raw_total_excluded - raw_total_excluded_currency - target_total_excluded - target_total_excluded_currency - total_excluded - total_excluded_currency But it is not. opw-6235909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284052 Forward-Port-Of: odoo/odoo#279335
German DATEV exports now correctly handle bank reconciliations involving three different currencies. The change splits these settlements through the appropriate clearing account so each exported line uses only one foreign currency, reducing export errors and improving accounting accuracy.
Original PR description
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank…
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank journal is held in another currency (C2), - the company uses a third currency (C3). - The existing export logic could not represent the bank liquidity and foreign AR/AP currencies separately in such cases. Fix: - Detect 3-currency cases from bank statement transactions and their liquidity line. - Use the DATEV clearing account (1360 SKR03 / 1460 SKR04) to split the transaction into two logical legs: - Bank → Clearing (bank journal currency) - AR/AP → Clearing (payer currency) - Emit the liquidity leg only once when multiple foreign AR/AP lines are reconciled against the same bank transaction. - Keep regular 1- and 2-currency transactions on the existing export path. Impact: - Correctly represents 3-currency bank settlements in DATEV. - Keeps each exported line in a single foreign currency. - Leaves manual entries and payment transactions outside this specific handling, as the scenario is specific to the bank liquidity line. taskID-5457547 Forward-Port-Of: odoo/enterprise#128876 Forward-Port-Of: odoo/enterprise#109010
This fix prevents errors when sales planning data is grouped by customer in setups where the customer field is not directly stored. It keeps planning and sales-related reporting reliable across different module configurations.
Original PR description
Before this commit, #122034 converted the related non-stored `partner_id` field in `planning.slot` into a compute non-stored field with a search method, the problem is that field was used as groupby inside a read_group which causes a traceback since the field is no longer reachable in SQL. This commit alters the groupby in problematic _read_group methods to use partner_id field when it is stored (when field service is installed) otherwise the groupby should be `sale_order_id.partner_id`. Forward-Port-Of: odoo/enterprise#128540
Opening the timesheet systray from a task now pre-fills the related project and task without changing the recorded time. This prevents users from accidentally losing an active timer value when logging time from task pages.
Original PR description
Before this commit, the prefill used when the user opens the timesheet systray when his current loaded page is a task, will alter the form view in the timesheet systray to set the project and task when those fields are unset. The problem is `unit_amount` is also given to 0 and so the timer is reset due to the prefill system. This commit makes sure the `unit_amount` field is not inside the prefill data to make sure the timer is no longer reset. opw-6481443 Forward-Port-Of: odoo/enterprise#128531
The Timesheet Assistant now clears the previous suggestion when a user unselects it before choosing another one. This prevents the wrong project or task from carrying over, reducing timesheet entry mistakes.
Original PR description
Steps to reproduce: ------------ - install timesheet_grid. - activate assistant. - select a suggestion and then unselect it. - select a different project suggestion. Issue: ----------- the project from the previous suggestion remains selected. cause: --------- currentRecord is not reset when a suggestion is unselected, so the previous suggestion's project and task are still reused. Fix: --------- reset currentRecord to null when the suggestion is unselected and showCreateForm is false. Effected pr-https://github.com/odoo/enterprise/pull/126450 task-6482312 Forward-Port-Of: odoo/enterprise#128374
A minor issue in the Sign app was corrected to prevent the system from trying to use a logging component that does not exist. This helps avoid unnecessary errors during document signing operations and improves reliability without changing user workflows.
Original PR description
See https://github.com/odoo/enterprise/pull/121960 Forward-Port-Of: odoo/enterprise#128748
Corrects a rounding mismatch in Peruvian electronic invoices that could cause down payment invoices to be rejected by the tax validation service. This helps ensure taxable amounts in the invoice XML stay consistent with line totals, including cases where one tax affects another tax base.
Original PR description
**Steps to reproduce:** - Install Accounting, Sales and l10n_pe_edi - Switch to a Peruvian company (e.g. PE Company) - Create a SO: * Customer: [a Peruvian customer] * Order Lines: | Product |…
**Steps to reproduce:**
- Install Accounting, Sales and l10n_pe_edi
- Switch to a Peruvian company (e.g. PE Company)
- Create a SO:
* Customer: [a Peruvian customer]
* Order Lines:
| Product | Quantity | Unit Price | Taxes |
| ------- | -------- | ---------- | ------- |
| any | 3.00 | 123.50 | VAT 18% |
| any | 2.00 | 27.544216 | 0% Ina |
| any | 1.00 | 43.490867 | 0% Exo |
- Confirm the SO
- Create a 40% down payment
- Confirm the down payment
- Process it to sent it to Peru UBL 2.1
**Issue:**
The following error message is returned by the OSE:
`3272|La base imponible a nivel de línea difiere de lainformación consignada en el comprobante - Detalle: xxx.xxx.xxx ticket : 20260000000000221633458 error: Error en la Linea Nro. :1. : 3272 (nodo: "cac:TaxSubtotal/cbc:TaxableAmount" valor: "148.20")`
**Cause:**
In the XML, one line has 148.19 for "cbc:LineExtensionAmount", but 148.20 for "cac:TaxSubtotal/cbc:TaxableAmount".
The issue is coming from the fact that "base_amount_currency" is used instead of "total_excluded_currency" for the computation of "cac:TaxSubtotal/cbc:TaxableAmount".
**Issue 2:**
When a tax is impacting the base amount of a following tax, its tax amount is not taken into account in "total_excluded_currency".
opw-6235909
Forward-Port-Of: odoo/enterprise#128881
Forward-Port-Of: odoo/enterprise#122310