Daily updates from Odoo
Navigate
Branch
Sunday, August 16, 2026
25 changes
6 changes
Resolved issues and error corrections
The Timesheet Assistant now keeps always-active work events, such as Google Meet meetings, from being interrupted by automatic AFK suggestions. This makes time suggestions and meeting descriptions more accurate for users reviewing their timesheets.
Original PR description
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet…
## Previous Behavior Before this PR: Users could have their always-active event split by an AFK event inside of Timesheet Assistant. AFK event durations were also inaccurate, and the Google Meet description was incorrect. ## Steps to Reproduce: 1. Generate an always-active event (e.g., join a meeting in Google Meet). 2. Generate non-key events (e.g., visit a website without an ActivityWatch rule). 3. Go AFK. 4. Generate a new non-key event. 5. The Timesheet Assistant will show three suggestions in the following order: an always-active suggestion, an AFK suggestion, and another always-active suggestion for the same activity. ## New Expected Behavior After this PR: The Timesheet Assistant now blocks the creation of AFK suggestions when the previous key event is marked as always-active. AFK event durations have been updated to ensure their values are accurate. The Google Meet description has also been corrected. task-[6431526](https://www.odoo.com/odoo/project/4105/tasks/6431526) Forward-Port-Of: odoo/enterprise#127028
Helpdesk tickets no longer show an SLA as reached immediately after it is assigned. The status now updates only when the ticket reaches the relevant target stage, giving teams more accurate SLA reporting while keeping lateness tracked separately.
Original PR description
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of…
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of the issue/feature this PR addresses: **Issue:** The `_compute_sla_reached` method in on `helpdesk_ticket.py` determines whether an SLA has been reached by checking if `exceeded_hours` is less than 0 on its `helpdesk.sla.status` records. Since every newly assigned SLA has a future deadline, `exceeded_hours` starts as negative (AKA <0), so the ticket is immediately flagged as `sla_reached = True` before any progress has been made. Conversely, a ticket that reaches its target stage after the deadline has `exceeded_hours >= 0`, so it's incorrectly flagged as `sla_reached = False` even though the SLA target was genuinely reached (it was just late). **Solution:** Change the domain in `_compute_sla_reached` to check `reached_datetime != False` instead of `exceeded_hours < 0`, matching the field already listed in the method's `@api.depends` and the same field `_sla_reach()` sets when a ticket enters its target stage. This makes `sla_reached` reflect actual stage progression rather than a time-remaining calculation. ### Current behavior before PR: A newly created ticket with a pending SLA shows `sla_reached = True` and `sla_success = True` immediately upon creation, before the ticket has moved to any target stage. SImilarly, a ticket that reaches its target stage after the SLA deadline is incorrectly marked `sla_reached = False`. ### Desired behavior after PR: `sla_reached` is False on ticket creation and only becomes True once the ticket actually enters the SLA's target stage. Lateness continues to be tracked separately and correctly via `sla_reached_late` opw-6361851 Forward-Port-Of: odoo/enterprise#127309 Forward-Port-Of: odoo/enterprise#126432
Mexican Point of Sale global invoices now ignore cancelled refund orders, so only completed refunds affect the invoice totals. This prevents invoice creation errors caused by subtracting unpaid cancelled refunds and helps businesses generate CFDI global invoices reliably.
Original PR description
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click…
Steps to reproduce: ------------------- 1. Install `l10n_mx_edi_pos` and set the company to Mexico. 2. In PoS, make an order with one product and pay it. 3. Open the order in the backend, click "Return Products" to make a refund, but don't pay it, cancel it instead. 4. From the same order, click "Return Products" again to make a second refund, and pay it normally. 5. Go to the orders list, select the main order and the paid refund (not the cancelled one), then Actions > Create Global Invoice. -> Observation: error in the global invoice. In the CFDI tab of the main order the line is "Send Global In Error", and hovering on it the detail says "Failed to distribute some negative lines". Why: ---- When we make the global invoice, we remove the refunds from the order. A cancelled refund was never paid, so we should not count it. But we were counting it too. So we removed the refund amount twice in our case, one for the paid refund, and one for the cancelled one, and we end up with an order with negative amount that cannot be distributed. The fix: -------- We now skip the cancelled orders when we search the refunds, the same way it is done above when we collect the refunded orders. opw-6261404 Forward-Port-Of: odoo/enterprise#127808 Forward-Port-Of: odoo/enterprise#120996
Fixing the QR code size and Robustness for ZATCA. 1. The QR code is now an embedded image SVG instead of an image fetched from the server, which makes it robust against Webkit quirks. 2. We set the QR size in the preview screen to 200px (back to what it was before https://github.com/odoo/odoo/pull/277813), and we make the QR size on the physical receipt 300px so it's big enough to be scanned easily. More info in the respective commit messages. opw-6399766 Forward-Port-Of: odoo/odoo#28
Original PR description
Fixing the QR code size and Robustness for ZATCA. 1. The QR code is now an embedded image SVG instead of an image fetched from the server, which makes it robust against Webkit quirks. 2. We set the QR size in the preview screen to 200px (back to what it was before https://github.com/odoo/odoo/pull/277813), and we make the QR size on the physical receipt 300px so it's big enough to be scanned easily. More info in the respective commit messages. opw-6399766 Forward-Port-Of: odoo/odoo#282627 Forward-Port-Of: odoo/odoo#282285
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was not tested properly: We are registered on PDP already. In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback. Steps to reproduce: 1. Install `l10n_fr_pdp` 2. Activate French E-Invoicing / PDP in Dem
Original PR description
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was…
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action.
But one case does not work / was not tested properly: We are registered on PDP already.
In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback.
Steps to reproduce:
1. Install `l10n_fr_pdp`
2. Activate French E-Invoicing / PDP in Demo mode
3. Create and post an invoice for a French PDP partner (e.g. just use the "FR Company")
4. Click "Send"
5. In the "move send" wizard disable the "French E-Invoicing (Demo)" option
6. Click on "Why should you use it?" in the warning
7. Click "Got it" in the window that pops up.
8. Traceback (see below)
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 36, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/res_config_settings.py", line 159, in button_peppol_reregister
self.ensure_one()
File "/home/odoo/src/odoo/odoo/models.py", line 6277, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.config.settings()
```
task-None
Thanks to KYMAG for finding / reporting the issue.
Forward-Port-Of: odoo/odoo#282406When loading the registry, borrow the request to avoid having using the cursor linked to it. Failing use case before the fix: install base odoo, in the web interface, activate and switch to a new language then install website. The installation will hang if the stable cache is invalidated because the installation may call `_` which will fallback to the request's language - reading the table from the request's cursor - while the installation tries to update the same of that same table in anothe
Original PR description
When loading the registry, borrow the request to avoid having using the cursor linked to it. Failing use case before the fix: install base odoo, in the web interface, activate and switch to a new language then install website. The installation will hang if the stable cache is invalidated because the installation may call `_` which will fallback to the request's language - reading the table from the request's cursor - while the installation tries to update the same of that same table in another cursor. Backport of odoo/odoo#281797 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282635 Forward-Port-Of: odoo/odoo#281798
7 changes
Resolved issues and error corrections
The timesheet assistant display now keeps durations readable, adds spacing, and wraps long titles instead of letting text overlap. This makes timesheet entries easier to scan, especially in chronological views with longer descriptions.
Original PR description
- enforce duration in one line - add a gap between the title and duration - wrap title if so long - adapt flex direction of chronological view to avoid overlapping of title and start time --- task-6432434 Forward-Port-Of: odoo/enterprise#126236
Helpdesk tickets no longer show an SLA as reached immediately after it is assigned. The status now changes only when the ticket reaches the relevant SLA stage, giving teams more accurate SLA reporting and separating late completion from actual completion.
Original PR description
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of…
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of the issue/feature this PR addresses: **Issue:** The `_compute_sla_reached` method in on `helpdesk_ticket.py` determines whether an SLA has been reached by checking if `exceeded_hours` is less than 0 on its `helpdesk.sla.status` records. Since every newly assigned SLA has a future deadline, `exceeded_hours` starts as negative (AKA <0), so the ticket is immediately flagged as `sla_reached = True` before any progress has been made. Conversely, a ticket that reaches its target stage after the deadline has `exceeded_hours >= 0`, so it's incorrectly flagged as `sla_reached = False` even though the SLA target was genuinely reached (it was just late). **Solution:** Change the domain in `_compute_sla_reached` to check `reached_datetime != False` instead of `exceeded_hours < 0`, matching the field already listed in the method's `@api.depends` and the same field `_sla_reach()` sets when a ticket enters its target stage. This makes `sla_reached` reflect actual stage progression rather than a time-remaining calculation. ### Current behavior before PR: A newly created ticket with a pending SLA shows `sla_reached = True` and `sla_success = True` immediately upon creation, before the ticket has moved to any target stage. SImilarly, a ticket that reaches its target stage after the SLA deadline is incorrectly marked `sla_reached = False`. ### Desired behavior after PR: `sla_reached` is False on ticket creation and only becomes True once the ticket actually enters the SLA's target stage. Lateness continues to be tracked separately and correctly via `sla_reached_late` opw-6361851 Forward-Port-Of: odoo/enterprise#126432
The Timesheet Assistant now recognizes time spent in spreadsheets and suggests it as “Working in Spreadsheet” instead of grouping it under Documents. This makes timesheet suggestions more accurate for users who work with spreadsheets.
Original PR description
## Behavior Before the Commit When a user spent time working in a spreadsheet, the Timesheet Assistant grouped this time under "Working in Documents". This occurred because "Spreadsheet" is a module rather than an application, and the Assistant only creates suggestions for applications. As a result, it attempted to fall back to an application and frequently defaulted to the "Documents" application. ## New Expected Behavior After this Commit: When a user spends time in a spreadsheet, the Timesheet Assistant now generates a "Working in Spreadsheet" suggestion. This is enabled by a dedicated list of non‑application modules that allows specific modules to be recognized even when they are not applications. task-[6438536](https://www.odoo.com/odoo/project/4105/tasks/6438536)
Fixes issues in the Timesheet Assistant that could cause errors when deleting entries or when existing timesheets were not created through the assistant. It also prevents internal event data from being unintentionally changed, making the assistant more stable for users.
Original PR description
## [FIX] timesheet_grid: avoid altering consumedEvents Before this commit, the objects inside consumedEvents attribute are altered because we keep the reference of those objects. This commit avoid altering the consumed events. ## [FIX] timesheet_grid: use recordsByStart instead of records
Timesheet activity suggestions now handle away-from-keyboard periods more accurately, so breaks are less likely to be missed or overwritten by other activity. This helps users and managers get a more reliable view of worked time and inactive periods.
Original PR description
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was…
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was not “always active.” This caused AFK events to be incorrectly overridden. 2. During event normalization, certain events were lost entirely, resulting in important events not being counted. 3. When merging two event timelines, zero‑duration gaps were treated as valid, preventing proper merging of surrounding events. 4. ActivityWatch sometimes produced empty gaps instead of AFK events, causing breaks to go unrecorded. ## New Expected Behavior After this Commit 1. Events now follow the updated priority system: a. Always‑active key events b. Always‑active non‑key events c. Non‑key AFK events d. Other key events e. Other non‑key events 2. Events are now shortened or split so that the latest event always has priority, while minimizing unnecessary event removal. 3. Zero‑duration gaps are skipped when merging event lists. 4. Any gap larger than 3 minutes, between the first and last event and containing no events is automatically filled with an AFK event. ## Additional Notes Because point 4 introduces additional AFK events, several tests were updated to reflect the new behavior. task-[6455412](https://www.odoo.com/odoo/project/4105/tasks/6455412)
When loading the registry, borrow the request to avoid having using the cursor linked to it. Failing use case before the fix: install base odoo, in the web interface, activate and switch to a new language then install website. The installation will hang if the stable cache is invalidated because the installation may call `_` which will fallback to the request's language - reading the table from the request's cursor - while the installation tries to update the same of that same table in anothe
Original PR description
When loading the registry, borrow the request to avoid having using the cursor linked to it. Failing use case before the fix: install base odoo, in the web interface, activate and switch to a new language then install website. The installation will hang if the stable cache is invalidated because the installation may call `_` which will fallback to the request's language - reading the table from the request's cursor - while the installation tries to update the same of that same table in another cursor. Backport of odoo/odoo#281797 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282628 Forward-Port-Of: odoo/odoo#281798
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was not tested properly: We are registered on PDP already. In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback. Steps to reproduce: 1. Install `l10n_fr_pdp` 2. Activate French E-Invoicing / PDP in Dem
Original PR description
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was…
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action.
But one case does not work / was not tested properly: We are registered on PDP already.
In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback.
Steps to reproduce:
1. Install `l10n_fr_pdp`
2. Activate French E-Invoicing / PDP in Demo mode
3. Create and post an invoice for a French PDP partner (e.g. just use the "FR Company")
4. Click "Send"
5. In the "move send" wizard disable the "French E-Invoicing (Demo)" option
6. Click on "Why should you use it?" in the warning
7. Click "Got it" in the window that pops up.
8. Traceback (see below)
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 36, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/res_config_settings.py", line 159, in button_peppol_reregister
self.ensure_one()
File "/home/odoo/src/odoo/odoo/models.py", line 6277, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.config.settings()
```
task-None
Thanks to KYMAG for finding / reporting the issue.
Forward-Port-Of: odoo/odoo#2824062 changes
Resolved issues and error corrections
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were written with a trailing comma inside the XML id, making the two checks silently fail for everyone. Only the accounting read group check, written correctly, was effective. Steps to reproduce: - create a service product with "Create on Order: Project & Task", sell it on a sale order and confirm it
Original PR description
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were…
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were written with a trailing comma inside the XML id, making the two checks silently fail for everyone. Only the accounting read group check, written correctly, was effective. Steps to reproduce: - create a service product with "Create on Order: Project & Task", sell it on a sale order and confirm it - create a down payment invoice from the sale order and post it - create a user with Sales "User: All Documents" access, Project "User" access and no accounting access - as that user, open the dashboard of the generated project and look at the Down Payments line of the profitability panel The Down Payments amount is displayed as plain text, while a user with accounting access can click it to open the related invoices, as intended for the salesperson too. Solution: Move the commas out of the group references. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278521
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was not tested properly: We are registered on PDP already. In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback. Steps to reproduce: 1. Install `l10n_fr_pdp` 2. Activate French E-Invoicing / PDP in Dem
Original PR description
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was…
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action.
But one case does not work / was not tested properly: We are registered on PDP already.
In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback.
Steps to reproduce:
1. Install `l10n_fr_pdp`
2. Activate French E-Invoicing / PDP in Demo mode
3. Create and post an invoice for a French PDP partner (e.g. just use the "FR Company")
4. Click "Send"
5. In the "move send" wizard disable the "French E-Invoicing (Demo)" option
6. Click on "Why should you use it?" in the warning
7. Click "Got it" in the window that pops up.
8. Traceback (see below)
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 36, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/res_config_settings.py", line 159, in button_peppol_reregister
self.ensure_one()
File "/home/odoo/src/odoo/odoo/models.py", line 6277, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.config.settings()
```
task-None
Thanks to KYMAG for finding / reporting the issue.
Forward-Port-Of: odoo/odoo#2824062 changes
Resolved issues and error corrections
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was not tested properly: We are registered on PDP already. In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback. Steps to reproduce: 1. Install `l10n_fr_pdp` 2. Activate French E-Invoicing / PDP in Dem
Original PR description
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was…
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action.
But one case does not work / was not tested properly: We are registered on PDP already.
In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback.
Steps to reproduce:
1. Install `l10n_fr_pdp`
2. Activate French E-Invoicing / PDP in Demo mode
3. Create and post an invoice for a French PDP partner (e.g. just use the "FR Company")
4. Click "Send"
5. In the "move send" wizard disable the "French E-Invoicing (Demo)" option
6. Click on "Why should you use it?" in the warning
7. Click "Got it" in the window that pops up.
8. Traceback (see below)
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 36, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/res_config_settings.py", line 159, in button_peppol_reregister
self.ensure_one()
File "/home/odoo/src/odoo/odoo/models.py", line 6277, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.config.settings()
```
task-None
Thanks to KYMAG for finding / reporting the issue.
Forward-Port-Of: odoo/odoo#282406Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear
Original PR description
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the…
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear from the original order line. Protect so_line during the write and drop the pending recompute: deleting an invoice must only make the hours invoiceable again, not change their allocation. Steps to reproduce: - Install Sales and Timesheets - Create a service product with invoice policy "Based on Timesheets" and "Create a task in a new project" - Create and confirm a sale order with this product - Log a timesheet on the generated task - Create the invoice (keep it in draft) - Remove the Sales Order Item from the task and from the project settings (or point them to a sale order item of another order) - Delete the draft invoice - Open the timesheet: its Sales Order Item is emptied (or replaced by the other order's item, whose delivered quantity now includes the hours sold on the original order), and the original line's delivered quantity is reset --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280154 Forward-Port-Of: odoo/odoo#279552
1 change
Resolved issues and error corrections
Swiss Payroll now refreshes employee payroll snapshots only when payroll-related information changes. This reduces unnecessary system notes and improves performance for companies using Swiss Payroll without changing payroll results.
Original PR description
### Description Employee monthly payroll snapshots are recomputed on every write to `hr.employee`, regardless of whether the modified fields impact payroll. This generates unnecessary chatter entries and introduces avoidable compute overhead, as `_create_or_update_snapshot` performs several expensive computations and updates many snapshot fields. ### Solution Only call `_create_or_update_snapshot` when a payroll-related field is modified. This avoids unnecessary snapshot recomputations, keeps the chatter clean, and improves the performance of databases using Swiss Payroll. opw-6285407
2 changes
Resolved issues and error corrections
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear
Original PR description
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the…
Deleting a draft customer invoice linked to timesheets resets their timesheet_invoice_id so the hours become invoiceable again. This write also marks the timesheets' so_line for recompute, and the re-derivation runs while the lines are no longer protected by the invoice link. When the task or project no longer resolves to a sale order item (e.g. it was unlinked after invoicing), the timesheets lose their sale order item or get reassigned to another one, so the delivered hours silently disappear from the original order line. Protect so_line during the write and drop the pending recompute: deleting an invoice must only make the hours invoiceable again, not change their allocation. Steps to reproduce: - Install Sales and Timesheets - Create a service product with invoice policy "Based on Timesheets" and "Create a task in a new project" - Create and confirm a sale order with this product - Log a timesheet on the generated task - Create the invoice (keep it in draft) - Remove the Sales Order Item from the task and from the project settings (or point them to a sale order item of another order) - Delete the draft invoice - Open the timesheet: its Sales Order Item is emptied (or replaced by the other order's item, whose delivered quantity now includes the hours sold on the original order), and the original line's delivered quantity is reset --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280154 Forward-Port-Of: odoo/odoo#279552
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was not tested properly: We are registered on PDP already. In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback. Steps to reproduce: 1. Install `l10n_fr_pdp` 2. Activate French E-Invoicing / PDP in Dem
Original PR description
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action. But one case does not work / was…
In this commit 004b56a5c31841bc0bf4a9f17902bbff8d0f509d we added the `l10n_fr_pdp.what_is_pdp` action as PDP version of the `account_peppol.what_is_peppol` action.
But one case does not work / was not tested properly: We are registered on PDP already.
In that case we just want to go back to the "move send" wizard. But the `what_is_pdp` action does not support that currently. So there is a traceback.
Steps to reproduce:
1. Install `l10n_fr_pdp`
2. Activate French E-Invoicing / PDP in Demo mode
3. Create and post an invoice for a French PDP partner (e.g. just use the "FR Company")
4. Click "Send"
5. In the "move send" wizard disable the "French E-Invoicing (Demo)" option
6. Click on "Why should you use it?" in the warning
7. Click "Got it" in the window that pops up.
8. Traceback (see below)
```
Traceback (most recent call last):
File "/home/odoo/src/odoo/odoo/http.py", line 2167, in _transactioning
return service_model.retrying(func, env=self.env)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/service/model.py", line 157, in retrying
result = func()
^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2134, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 2382, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/addons/base/models/ir_http.py", line 333, in _dispatch
result = endpoint(**request.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/http.py", line 754, in route_wrapper
result = endpoint(self, *args, **params_ok)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/web/controllers/dataset.py", line 36, in call_kw
return call_kw(request.env[model], method, args, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/odoo/api.py", line 535, in call_kw
result = getattr(recs, name)(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/addons/account_peppol/models/res_config_settings.py", line 159, in button_peppol_reregister
self.ensure_one()
File "/home/odoo/src/odoo/odoo/models.py", line 6277, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.config.settings()
```
task-None
Thanks to KYMAG for finding / reporting the issue.
Forward-Port-Of: odoo/odoo#2824064 changes
Enhancements to existing features
Timesheet users can now select multiple assistant suggestions by holding the mouse button and moving over them, making batch actions like deleting suggestions or creating timesheets quicker. The update also prevents an unwanted new Odoo page from opening when using Ctrl-click on a suggestion.
Original PR description
Currently when the user uses ctrl + click on a suggestion, a new odoo page is opened. This is an undesirable side effect and it is removed in this commit. Also, users have to manually click on each suggestion when they want to remove them in batch, or create one timesheet for a bunch of suggestion. This commit lets user hover over suggestion with the mouse button pressed to select them. task-6385047 Forward-Port-Of: odoo/enterprise#127311 Forward-Port-Of: odoo/enterprise#124642
Resolved issues and error corrections
The timesheet assistant now preserves a project that a user manually selects on the timesheet form, even when they switch to another suggestion linked to a different project. This prevents accidental overwriting and helps users avoid incorrect project entries before saving.
Original PR description
Steps to reproduce: - Select an unmatched suggestion. - Select Project A on the timesheet form (do not save it yet). - Select another suggestion matched to Project B. Observed behavior: Project A is overridden by Project B. Expected behavior: Project A remains selected on the timesheet. By initializing `project_id` with the current record's data, we prevent the suggestion loop from overwriting the user's manual selection. task-6410844 Forward-Port-Of: odoo/enterprise#127423 Forward-Port-Of: odoo/enterprise#126450
The Timesheet Assistant can now correctly detect activity in Google Sheets and Google Slides when suggesting timesheet entries. This fixes missed suggestions caused by different spacing characters in application names, helping users capture work more reliably.
Original PR description
## Behavior Before Commit : Due to the fact that the Timesheet Assistant rule on Google Slides & Google Sheets was missing or broken, the Assistant was unable to generate suggestions based on the use of these applications. The reason why the Assistant rule is broken for Google Sheets and Google Slides is because the regex rules assume the character between "Google" and "Slides" or between "Google" and "Sheets" is a "normal" space character, which is not the case. ## New Expected Behavior After this Commit : The updated rules now expect a generic space character between "Google" and "Slides" and between "Google" and "Sheets". This is done through the '\s' character in regex. task-[6445752](https://www.odoo.com/odoo/project/4105/tasks/6445752)
This fix prevents new Helpdesk tickets from being incorrectly shown as having already met their SLA. SLA completion is now marked only when the ticket reaches the required stage, while late completion remains tracked separately.
Original PR description
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of…
### Steps to Reproduce: 1. Go to Helpdesk and create an SLA 2. Create a new Ticket 3. Use Studio to add the field `sla_reached` 4. Apply the SLA 5. Notice that the field is True ### Description of the issue/feature this PR addresses: **Issue:** The `_compute_sla_reached` method in on `helpdesk_ticket.py` determines whether an SLA has been reached by checking if `exceeded_hours` is less than 0 on its `helpdesk.sla.status` records. Since every newly assigned SLA has a future deadline, `exceeded_hours` starts as negative (AKA <0), so the ticket is immediately flagged as `sla_reached = True` before any progress has been made. Conversely, a ticket that reaches its target stage after the deadline has `exceeded_hours >= 0`, so it's incorrectly flagged as `sla_reached = False` even though the SLA target was genuinely reached (it was just late). **Solution:** Change the domain in `_compute_sla_reached` to check `reached_datetime != False` instead of `exceeded_hours < 0`, matching the field already listed in the method's `@api.depends` and the same field `_sla_reach()` sets when a ticket enters its target stage. This makes `sla_reached` reflect actual stage progression rather than a time-remaining calculation. ### Current behavior before PR: A newly created ticket with a pending SLA shows `sla_reached = True` and `sla_success = True` immediately upon creation, before the ticket has moved to any target stage. SImilarly, a ticket that reaches its target stage after the SLA deadline is incorrectly marked `sla_reached = False`. ### Desired behavior after PR: `sla_reached` is False on ticket creation and only becomes True once the ticket actually enters the SLA's target stage. Lateness continues to be tracked separately and correctly via `sla_reached_late` opw-6361851 Forward-Port-Of: odoo/enterprise#127309 Forward-Port-Of: odoo/enterprise#126432
1 change
Resolved issues and error corrections
Fixes an issue where running task or ticket timers could jump between values, show negative time, or calculate the wrong elapsed time after repeated stop/start and page reloads. This keeps the visible timer reliable for employees tracking work time and reduces the risk of incorrect timesheet entries.
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