Sunday, August 23, 2026
9 changes · saas-19.4
Resolved issues and error corrections
This fix prevents errors when rounded work-hour values land exactly on the next hour, such as 16.9959 becoming 17:00. It improves reliability for computed or aggregated hour values and safely handles values that round to the end of the day.
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 point-of-sale down payments are now handled correctly when a sales order is later settled or invoiced. This prevents customers from being charged 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
Closing and reopening the note composer could show a confirmation popup that crashed when users pressed Escape or arrow keys. This fix makes those key presses safely do nothing, preventing an interruption while logging notes.
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 an attendance calculation issue where a shift ending exactly at midnight could be counted as part of the next day. Overtime recomputation now uses the right day's attendance records, preventing incorrect overtime balances for employees with split shifts or midnight-ending work periods.
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#283226Date and time changes shown in the chatter now use the current user's timezone and locale instead of falling back to UTC. This makes tracked changes clearer for teams working across different languages and time zones by also showing the timezone explicitly.
Original PR description
Although the code was attempting to render the tracking values in the current user's timezone. It did not work. While fixing this, we also wanted to make the time clearer in multi-language/timezone settings: - Date(time) is now formatted in the same way it is for datetime fields in the frontend - The timezone is added after it, so we know exactly what time is meant - Those two fields are reprocessed in the chatter so that we simply show them in the user's locale task-6456370 Forward-Port-Of: odoo/odoo#281769
Mentioning a contact linked to multiple active users in a mail sub-channel no longer triggers an error. The system now checks each user's notification preference and invites the contact when at least one linked user allows channel notifications, keeping discussions flowing for administrators and teams.
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
The Timesheet Assistant now clears the previously selected suggestion when a user unselects it. This prevents an old project or task from carrying over when the user chooses a different suggestion, reducing incorrect timesheet entries.
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
This fix prevents the Sign app from trying to use a logging component that does not exist. It helps avoid unnecessary technical 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
German DATEV exports now handle bank payments involving three different currencies by splitting them into clear bank and receivable/payable parts. This prevents export issues and keeps each DATEV line aligned with a single foreign currency, improving accuracy for companies with multi-currency bank settlements.
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