Daily updates from Odoo
Thursday, October 30, 2025
23 changes · saas-18.3
Resolved issues and error corrections
Opening the duplicate transaction wizard without a linked journal no longer causes an error. This improves reliability for Accounting users and avoids a disruptive traceback when accessing the view.
Original PR description
When user opens the ``account.duplicate.transaction.wizard.form`` view, a traceback appears.
Steps to reproduce the error:
- Install ``Accounting`` module
- Using Open View, Open ``account.duplicate.transaction.wizard.form`` view
Traceback:
```py
UndefinedFunction: operator does not exist: integer = boolean
LINE 5: WHERE st_line.journal_id = false
^
```
https://github.com/odoo/enterprise/blob/8146cfc7b47ba8536f0fa5208cc69685371b55b8/account_online_synchronization/models/account_journal.py#L278
When the view is opened, the ``_compute_provider_duplicate_ids`` method is triggered,
which calls ``_get_provider_duplicate_transactions`` method.
Since no journal is linked to the wizard, it will raise the traceback from the above line.
ref: 218e8a365b153a202d062152ff69234482bcccf2
sentry-6943450225
Forward-Port-Of: odoo/enterprise#97196This fixes a database restore error that could happen if the default Odoo OAuth provider had been deleted. Restores can now complete normally in that case, reducing avoidable downtime and support intervention.
Original PR description
**Description of the issue/feature this PR addresses:** When a user has deleted the Odoo Oauth provider, an error occurs when restoring the database. **Current behavior before PR:** You'll get this…
**Description of the issue/feature this PR addresses:**
When a user has deleted the Odoo Oauth provider, an error occurs when restoring the database.
**Current behavior before PR:**
You'll get this error:
```
odoo.service.db.restore_db(dbname, backup, copy, **extra_kwargs)
File "<decorator-gen-27>", line 2, in restore_db
File "/opt/ou/odoo/odoo/service/db.py", line 44, in if_db_mgt_enabled
return method(self, *args, **kwargs)
File "/opt/ou/odoo/odoo/service/db.py", line 360, in restore_db
env['ir.config_parameter'].init(force=True)
File "/opt/ou/odoo/addons/auth_oauth/models/ir_config_parameter.py", line 13, in init
oauth_oe = self.env.ref('auth_oauth.provider_openerp')
File "/opt/ou/odoo/odoo/api.py", line 611, in ref
res_model, res_id = self['ir.model.data']._xmlid_to_res_model_res_id(
File "/opt/ou/odoo/odoo/addons/base/models/ir_model.py", line 2059, in _xmlid_to_res_model_res_id
return self._xmlid_lookup(xmlid)[1:3]
File "<decorator-gen-43>", line 2, in _xmlid_lookup
File "/opt/ou/odoo/odoo/tools/cache.py", line 90, in lookup
value = d[key] = self.method(*args, **kwargs)
File "/opt/ou/odoo/odoo/addons/base/models/ir_model.py", line 2052, in _xmlid_lookup
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system: auth_oauth.provider_openerp
Error: External ID not found in the system: auth_oauth.provider_openerp
```
**Desired behavior after PR is merged:**
No error will occur
The afflicted versions are AFAIK, **16.0**, **17.0**, **18.0**, and **19.0**
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#233633This commit is a follow-up of this commit [[1]]. The aim of this commit is improving the Finnish translations for the localization. no task id Co-authored-by: [sahak-fin](https://github.com/sahak-fin) <sahak@odoo.com> [1]: https://github.com/odoo/odoo/commit/d0017410646500928bf8fe08077f21569c1fa47e --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233482 Forward-Port-Of: odoo/odoo#233042
Original PR description
This commit is a follow-up of this commit [[1]]. The aim of this commit is improving the Finnish translations for the localization. no task id Co-authored-by: [sahak-fin](https://github.com/sahak-fin) <sahak@odoo.com> [1]: https://github.com/odoo/odoo/commit/d0017410646500928bf8fe08077f21569c1fa47e --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233482 Forward-Port-Of: odoo/odoo#233042
The Chilean electronic invoicing process now selects a single matching recipient company when multiple companies share the same tax ID. This avoids processing errors for businesses with branches or duplicate RUT records.
Original PR description
Before this commit, if multiple companies shared the same RUT (VAT), for example companies with branches, searching a recipient could return more than one company record. This could lead to errors when accessing variables that expect a single record. To prevent this issue, the search is now limited to one company record. OPW-5128543 Forward-Port-Of: odoo/enterprise#98352
The attendance management "To approve" filter now shows records even when they have zero overtime. This lets managers review, edit, or approve all relevant attendances instead of missing entries that may still need attention.
Original PR description
Currently attendances having 0 overtime are hidden by the filter "To approve", which is weird because managers might want to manually edit them, or approve them. task-5189190 Forward-Port-Of: odoo/odoo#232796
Fixes Swedish point-of-sale fiscal blackbox validation so orders are correctly checked and synced again. It also restores reliable receipt reprint tracking and corrects the organization number format, helping businesses stay compliant with Swedish POS requirements.
Original PR description
Before this commit, the Swedish blackbox was completely broken in 18.0 because the `push_single_order` function is no longer used. To fix this, the same approach as `pos_blackbox_be` was used, where the `preSyncAllOrders` function was overridden instead. In addition, the old receipt reprinting logic was no longer working, and so it now uses the `nb_print` field to keep track of the number of reprints. Finally, we also forward port a fix from 17.0 (ddbc1fc) to correct the format of the organisation number, which for some reason was not forward ported originally. task-5077448 Forward-Port-Of: odoo/enterprise#98179 Forward-Port-Of: odoo/enterprise#98139
This fixes an issue where users could not save a changed cost on an expense category when vendor taxes from multiple companies were configured. Businesses using multiple companies can now update expense category costs without being blocked by company-specific tax settings.
Original PR description
Steps to reproduce: - Create 2 companies - Create a tax one each - Create an expense category - Set the 2 taxes as Vendor Taxes - Select only one of the companies - Change the cost of the expense category - Try saving --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232291
Live chat session reports now display the rating label when sessions are grouped by rating, instead of showing the underlying rating value. This makes grouped views easier for teams to read and interpret when reviewing customer feedback.
Original PR description
The group by rating in the live chat session views shows the last rating value instead of the rating text. This commit fixes the issue. task-4770430 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Fixed an issue in Manufacturing where overlapping work order time entries could be removed or adjusted after saving. This keeps tracked production time accurate and prevents loss of work order history.
Original PR description
Issue: In this bug, workorder duration inverse is causing some time_ids to be deleted. To reproduce: 1- Create a db with mrp installed, and enable work orders in Setting 2- Create a MO, and confirm…
Issue:
In this bug, workorder duration inverse is causing some time_ids to be deleted.
To reproduce:
1- Create a db with mrp installed, and enable work orders in Setting
2- Create a MO, and confirm it
3- Add a new work order to the MO
4- Add two time tracking lines:
- First one 10:00 -> 12:00
- Second one 10:00 -> 11:00
5- As you see, duration reflects duration of first line as it is the interval duration
6- Save and close work center form. Then save MO form.
7- Open work orders again: As you see second line is unlinked
Cause:
The reason to this bug, is because in Enterprise, the `_compute_duration` override changes the logic of how duration is computed but the inverse function doesn't reflect the same logic.
To be specific this is the compute function override:
https://github.com/odoo/enterprise/blob/3cbe2bbbfd989a3daaa32769a843aeaa09c7ed3e/mrp_workorder/models/mrp_workorder.py#L757-L766
In which duration is calculated using get_duration:
https://github.com/odoo/enterprise/blob/3cbe2bbbfd989a3daaa32769a843aeaa09c7ed3e/mrp_workorder/models/mrp_workorder.py#L828-L837
Which doesn't sum the durations, but calculates the intervals duration counting overlaps only once.
However, there is no override of inverse method in Enterprise, meaning that the logic behind inverse will not match with this logic. In the inverse it is assumed duration is sum of all time_ids intervals:
https://github.com/odoo/odoo/blob/9b286285a6c66bc2d629eacf651c3439cffb55cc/addons/mrp/models/mrp_workorder.py#L355-L400
As a result, if time_ids overlap:
new_order_duration < old_order_duration
As a result some time_ids will be unlinked and some will have duration changed.
Fix:
Inside the inverse function in Community we can do:
```diff
+ old_order_duration = order.get_duration()
- sum(order.time_ids.mapped('duration'))
```
As get_duration in Odoo Community is:
https://github.com/odoo/odoo/blob/9b286285a6c66bc2d629eacf651c3439cffb55cc/addons/mrp/models/mrp_workorder.py#L889-L899
The order.get_duration will be sum of duration of all time_ids in community, hence the logic will be unchanged.
In Enterprise, this is going to reflect the logic implemented in override of get_duration, as a result the duration logic will be consistent in compute and inverse function.
opw-5082477This fixes an issue where overlapping time tracking entries on manufacturing work orders could be wrongly removed after saving. Work order duration calculations now stay consistent, helping manufacturers keep accurate production time records.
Original PR description
#### Issue: In this bug, workorder duration inverse is causing some time_ids to be deleted. To reproduce: 1- Create a db with mrp installed, and enable work orders in Setting 2- Create a MO, and…
#### Issue:
In this bug, workorder duration inverse is causing some time_ids to be deleted.
To reproduce:
1- Create a db with mrp installed, and enable work orders in Setting
2- Create a MO, and confirm it
3- Add a new work order to the MO
4- Add two time tracking lines:
- First one 10:00 -> 12:00
- Second one 10:00 -> 11:00
5- As you see, duration reflects duration of first line as it is the interval duration
6- Save and close work center form. Then save MO form.
7- Open work orders again: As you see second line is unlinked
#### Cause:
The reason to this bug, is because in Enterprise, the `_compute_duration` override changes the logic of how duration is computed but the inverse function doesn't reflect the same logic.
To be specific this is the compute function override: https://github.com/odoo/enterprise/blob/3cbe2bbbfd989a3daaa32769a843aeaa09c7ed3e/mrp_workorder/models/mrp_workorder.py#L757-L766
In which duration is calculated using get_duration: https://github.com/odoo/enterprise/blob/3cbe2bbbfd989a3daaa32769a843aeaa09c7ed3e/mrp_workorder/models/mrp_workorder.py#L828-L837
Which doesn't sum the durations, but calculates the intervals duration counting overlaps only once.
However, there is no override of inverse method in Enterprise, meaning that the logic behind inverse will not match with this logic. In the inverse it is assumed duration is sum of all time_ids intervals: https://github.com/odoo/odoo/blob/9b286285a6c66bc2d629eacf651c3439cffb55cc/addons/mrp/models/mrp_workorder.py#L355-L400
As a result, if time_ids overlap:
new_order_duration < old_order_duration
As a result some time_ids will be unlinked and some will have duration changed.
#### Fix:
Inside the inverse function in Community we can do:
```diff
+ old_order_duration = order.get_duration()
- sum(order.time_ids.mapped('duration'))
```
As get_duration in Odoo Community is:
https://github.com/odoo/odoo/blob/9b286285a6c66bc2d629eacf651c3439cffb55cc/addons/mrp/models/mrp_workorder.py#L889-L899
The order.get_duration will be sum of duration of all time_ids in community, hence the logic will be unchanged.
In Enterprise, this is going to reflect the logic implemented in override of get_duration, as a result the duration logic will be consistent in compute and inverse function.
However, this might cause another issue:
If `order.duration` is not computed yet, and inverse method `_set_duration` is called, then `get_duration` inside `_set_duration` will be called before the `get_duration` in compute method. As a result there might be a small unexpected time difference between `old_order_duration` and `new_order_diuration`. To avoid that inside `get_working_duration` we can use cursor now instead:
```diff
+ now = self.env.cr.now()
- now = datetime.now()
```
opw-5082477A leftover call to a removed function was eliminated from the self-ordering service. This prevents avoidable errors in point-of-sale self-ordering flows and helps keep the customer ordering experience stable.
Original PR description
Before this commit, there was still a call to the resetTableIdentifier, even though the function had been removed, which could cause errors. opw-5166737 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix lets point of sale users search for products whose variants are created dynamically from template attributes. It prevents products from being missed at checkout just because their specific variant has not been generated yet.
Original PR description
Before this commit, it was not possible to search a product that had a dynamic attribute configured on its template, since no product variant was created yet. opw-5188725 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Calendar events created in week view now display the correct start and end times when they span multiple days. This prevents misleading times from appearing on each day segment, helping users read schedules more accurately.
Original PR description
When creating an event in week view spanning over multiple days, all parts of the event display 12pm as end date (except the last one) and 00am as the start date (except the first one). This fix allow calendar views to display the correct hour in week view when the event spans multiple days. task-4700158 Forward-Port-Of: odoo/odoo#230624
Deleting a signer role in Sign templates now works correctly when that role has radio button fields. This prevents an error that could interrupt template editing and lets users manage signing roles more reliably.
Original PR description
Before this commit, when deleting a Signer role that already had a radio button dropped in the Template, it would trigger a traceback since the were trying to delete radio buttons individually. This was problematic because radio buttons are deleted in chain, so when deleting the first, we already delete all the remaining radio buttons and its chain link. After this commit, no issue is raised anymore when deleting a signer role, as radio buttons already deleted are now skipped in the code. task-5130925 Forward-Port-Of: odoo/enterprise#96097
This fixes incorrect leave duration calculations for Indian HR holidays when sandwich leave rules include weekends or public holidays. Employees and HR teams now see accurate leave balances, avoiding negative or inflated durations when leave spans non-working days or linked leave requests change.
Original PR description
Before this PR, if you created a leave of a type that had sandwich leave enabled on a non-working day, it would show a negative duration. This PR fixes some issues related to sandwich leave cases…
Before this PR, if you created a leave of a type that had sandwich leave enabled on a non-working day, it would show a negative duration. This PR fixes some issues related to sandwich leave cases (where Saturday and Sunday are considered non-working days): - Friday - Monday across weekend - counted (4 days). - Hour-based leave types: weekend bridging increases hours accordingly - Public holiday in the middle (Tue-Thu with Wed PH) - counted (3 days). - Stop/Start exactly on a public holiday(Tue-Wed(Public holiday), or Wed(Public holiday)-Thu) - trimmed to 1 day. - Public holiday only - 0 days. - Two single-day leaves around a Public holiday - When the second leave is created, it bridges via a public holiday (2 days), - The first one remains 1 day if it stands alone - Mixed leave types: - If the linked leave type doesn’t have sandwich enabled, no sandwich rules. - If both leave enable sandwich (with different types) - sandwich rule applies - Refusing/canceling a linked leave must immediately adjust the other side’s duration (e.g., Monday refused - Friday drops from 3 - 1 day) Task-4430044 Co-authored-by: @mepe-odoo Forward-Port-Of: odoo/odoo#233613 Forward-Port-Of: odoo/odoo#193186
This fixes electronic invoice generation so tax-included product prices are reported with enough precision to pass Peppol validation. Businesses using UBL/BIS3 invoicing should see fewer rejected invoices caused by small rounding differences.
Original PR description
At the moment, the UBL's Price/PriceAmount node is rounded to the same number of decimals as the database's product price precision. This causes a Peppol schematron validation error due to rule PEPPOL-EN16931-R120 in the case where the user uses tax-included prices. For example, if you have a tax-included unit price of 12.95, a quantity of 8 and a 21% tax, then the tax-excluded subtotal is 85.62. Divide 85.62 by 8 and you get a raw unit price of 10.7025. But if we round to 2 decimal places, we get 10.7 but `10.7 * 8 = 85.6 != 85.62`. Solution: We need to round the unit price to enough decimal places to ensure that unit price * quantity ~= line subtotal (with a tolerance of less than 0.02) opw-5072134 Forward-Port-Of: odoo/odoo#226869
Italian electronic invoices that combine ENASARCO with a regular withholding tax no longer fail validation incorrectly. This prevents valid invoices from being blocked during sending while keeping checks that avoid invalid tax combinations.
Original PR description
In the Italian localization, we validate that each invoice line has at most one tax per kind (VAT, withholding, pension fund). In Italy, a product cannot have more than one VAT tax. Also, the…
In the Italian localization, we validate that each invoice line has at most one tax per kind (VAT, withholding, pension fund). In Italy, a product cannot have more than one VAT tax. Also, the FatturaPA XML structure only allows global declarations for withholding and pension fund taxes — on the line level, it can only specify if those taxes apply, not which ones. To reflect this, we enforce one tax per kind per line. This validation was broken and recently fixed. However, ENASARCO is a special case: it acts both as a withholding and a pension fund tax. We added the Withholding flag recently (odoo/odoo#226968). In realistic cases (e.g., a line with VAT + withholding 23% RIT AG + ENASARCO), the validation fails and the user gets a blocking error in account.move.send. Since ENASARCO already has dedicated support through the AltriDatiGestionali tag on the line, we allow it to pass the check as if it were only a pension fund, restoring the previous behavior before we added the withholding flag. Some validation added and fields clear up in the tax editing phase, preventing invalid cases. Ticket [link](https://www.odoo.com/odoo/project.task/5154223) opw-5154223 Forward-Port-Of: odoo/odoo#232140
Corrects a rounding problem in Mexican electronic invoicing that could block global invoices when discounts created small decimal differences. This helps affected businesses validate and issue compliant invoices without receiving the CFDI40108 error.
Original PR description
Steps to reproduce: ------------------- * Create an invoice with the following line: * Unit price: 47.25, Qty: 1, Taxes: 16%, Discount 50% * Confirm, create a global invoice > Observation: Error ```…
Steps to reproduce: ------------------- * Create an invoice with the following line: * Unit price: 47.25, Qty: 1, Taxes: 16%, Discount 50% * Confirm, create a global invoice > Observation: Error ``` Code : CFDI40108 Message : El TipoDeComprobante es I,E o N, el importe registrado en el campo no es igual al redondeo de la suma de los importes de los conceptos registrados. ``` Why the fix: ------------ The issue occurs because the `descuento` value, originally 23.625, is now being corrected to 23.615 which leads to `importe` having a value of 23.635 which round up to 23.64 and not 23.63. https://github.com/odoo/enterprise/blob/08564f3312c255f2f3ab95cef5a9bfc57727bd1f/l10n_mx_edi/models/l10n_mx_edi_document.py#L1111 https://github.com/odoo/enterprise/blob/08564f3312c255f2f3ab95cef5a9bfc57727bd1f/l10n_mx_edi/models/l10n_mx_edi_document.py#L1336 Before this commit https://github.com/odoo/enterprise/commit/39759babddc732a312ec5cd6a60a2f1819abc62c the discount value was being rounded when corrected. It would end up being evaluated to 23.62. To not bring back the issue the fixed by the mentioned commit we round the discount when generating the global invoice cfdi values. Now `importe` will have a value of 23.63 as `descuento` is rounded to 23.62. opw-5023597 Forward-Port-Of: odoo/enterprise#94438
Authorized HR Payroll users can now resend payslips by email without being blocked by missing document access rights. The change ensures the payslip link needed in the email is generated after the user permission check, so the intended button works reliably.
Original PR description
Hr Payroll users that are meant to be able to use the Resend Payslip by email button do not have enough access right to get the documents token to put into the email "Your Payslip" button. Add a sudo on the payslip to get the document access url after the check of user role has been done. If have the right to use the button, sudo the rest. Task-5049444
This fixes an issue where live chat operators with standard permissions could not pin a customer message after a chatbot handed the conversation over to them. The change prevents an unnecessary chatbot permission check during message pinning, keeping live chat sessions running smoothly for support teams.
Original PR description
To reproduce (on runbot): - S1: Connect as "admin", leave the "YourWebsite.com" then logout - S1: Connect as "demo" user - S2: As public user, go to /contactus and start a chat session - S2: On the chatbot interaction, choose "I have a pricing question" (this will forward to the operator) - S2: enter a message - S1: On the livechat session, try to pin the last user message Since 1ecddc3d79dd an `AccessError` is raised, as the "demo" user (which is only `LiveChat / User`) don't have access to the chatbot step anymore. As we're not in the interacting with the chatbot when pinning a message, simplify skip that part if there is no "chatbotx answner" context to prevent the `AccessError`. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Creating a new salary offer from an existing offer now produces a valid configurator link with a unique token. This prevents broken offer links showing an invalid token value, helping recruiters share salary offers reliably.
Original PR description
_______________________________________ ## Short functional explanation of the error When creating an offer on the page of another offer, the salary configurator url doesn't contain a token, but instead, contains token = false. ## Reproduction Steps 1. Open the recruitment module. If there's no job position nor application, create some. 2. Open an existing application and click on Generate Offer. 3. Click on New on the top left of the screen. 4. Fill the new application and click on save. ### Expected behavior The field 'Link' contains an URL with, at the end, &token=x, with x a randomly generated token. ### Unexpected behavior The field 'Link' contains an URL with, at the end, &token=False. ## Origin of the issue The token generation code wasn't called when creating a new offer the way described in reproduction steps. _________________________________________ opw-4885796 ---
The spreadsheet component has been updated to the latest available version for this Odoo release. This fixes an upgrade mapping issue that could affect version transitions, helping ensure smoother maintenance and fewer spreadsheet-related upgrade problems.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/def777822b [REL] 18.3.25 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/2df67bbbd1 [FIX] upgrade: half-versions are missing in mapping [Task: 5116401](https://www.odoo.com/odoo/2328/tasks/5116401) Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya <rmbh@odoo.com> Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
This fix ensures Turkish e-invoicing tax setup only creates taxes for main companies, not their branch companies. It helps avoid duplicate tax records during setup, reducing accounting configuration errors for businesses with branch structures.
Original PR description
Adds parent_id check on the domain to ensure taxes are only loaded for root companies. This prevents duplicate tax creation on branch (child) companies when initializing tax templates. task-5176333 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#232679