Daily updates from Odoo
Wednesday, July 22, 2026
13 changes · master
Enhancements to existing features
This draft change appears to update Argentinian localization withholding support, likely improving how businesses handle local tax withholding requirements. Because no changed files or commit details were provided, the exact user impact cannot be determined from the available information.
Payroll salary computation lines now show routine values in a muted style instead of hiding them. This keeps payslip screens easier to scan while still allowing users to edit quantities, rates, or amounts when needed.
Original PR description
In this previous PR (https://github.com/odoo/enterprise/pull/109925) we made obvious values in the salary computation (quantity = 1, rate = 100, amount = total) invisible to decrease the visual clutter. However, this way we are no longer able to modify them since they don't show up. To allow for modifying while maintaning the distinction between important values and obvious ones, we make them muted instead of invisible. Task: 6324418
The timesheet assistant now offers clearer placeholder text, more useful default filters, and rounded billable and non-billable percentages. This makes the timesheet experience easier to read and navigate for users managing time entries.
Original PR description
This PR improves a few UX elements in the timesheets assistant, namely placeholders, default filters, and rounding (non-)billable percentages to the nearest integer. Task-6218571
Dominican companies can now generate the DGII Format 606 purchase report directly from the Journal Audit report. This helps prepare monthly vendor bill and refund data for submission to the DGII portal, reducing manual work and improving compliance support.
Original PR description
Dominican companies must report their monthly purchases to the DGII in the Format 606 layout, pasted into the DGII pre-validator and uploaded to the DGII portal. Add a 'Generate 606 DGII' button on the Journal Audit report for DO companies, exporting one row per posted vendor bill/refund of the period: - partner RNC/Cédula and identification type (foreign suppliers are not reported) - NCF, and the NCF of the reversed bill for refunds - goods/services amounts split per invoice line product type, lines without a product counting as services - ITBIS/ISR amounts summed per tax grid, ISC and tip per tax group - payment date from the last reconciled counterpart - purchase type, payment type and ISR withholding type from the new l10n_do fields task-6118976
Resolved issues and error corrections
Fixes Peruvian electronic invoices so detraction withholding amounts are converted and shown in Peruvian soles even when the company currency is USD. This prevents incorrect XML submissions to SUNAT and wrong currency symbols on invoice PDFs.
Original PR description
**Steps to reproduce:** * Install the **l10n_pe_edi** module. * Change the company currency to **USD**. * Configure **Peruvian detraction** settings: * Set a **withholding percentage** on a product.…
**Steps to reproduce:**
* Install the **l10n_pe_edi** module.
* Change the company currency to **USD**.
* Configure **Peruvian detraction** settings:
* Set a **withholding percentage** on a product.
* Set a **withholding code** on the same product.
* Create a customer invoice in **USD**.
* Set the **Operation Type** to **[1001] Operation Subject to Detraction**.
* Add the configured product to the invoice.
* Confirm the invoice, **send it to SUNAT** by *process now**, and generate the ZIP which has XML.
**Observed behavior:**
* The generated XML contains: `<cbc:Amount currencyID="PEN">116.82</cbc:Amount>` The `currencyID` is `PEN` but the amount is the raw USD value instead of being converted to PEN using the exchange rate.
* The PDF report also shows the withholding amount with the wrong currency symbol.
**Cause:**
* `_l10n_pe_edi_get_spot()` computed `spot['amount']` as `amount_total_signed * percent`, where `amount_total_signed` is stored in the **company currency**. When the company currency is PEN this works correctly, but when it is changed to USD the value is in USD while the XML node hardcodes `currencyID="PEN"`.
* `spot['currency']` was also set to `company_id.currency_id`, so the PDF rendered the amount with the wrong currency symbol.
* In `_add_invoice_payment_terms_nodes`, `spot_amount` was selected via `spot['amount'] if invoice.currency_id == invoice.company_id.currency_id` which relied on company currency being PEN as a proxy for the invoice being in PEN, breaking when company currency is USD.
**Fix:**
* In `_l10n_pe_edi_get_spot()`, compute `spot['amount']` by explicitly converting `amount_total` from the invoice currency to PEN using `currency_id._convert(..., env.ref('base.PEN'), ...)`, ensuring the detraction amount is always in PEN regardless of the company currency.
* Set `spot['currency']` to `env.ref('base.PEN')` so the PDF report always displays the withholding amount with the correct PEN symbol.
* In `_add_invoice_payment_terms_nodes`, always use `spot['spot_amount']` (invoice currency amount) for the `FormaPago`/`Cuota` arithmetic, since `spot['amount']` is now exclusively the PEN amount for the detraction XML node.
opw-6327571
Forward-Port-Of: odoo/enterprise#125063
Forward-Port-Of: odoo/enterprise#123782Appraisals now select the template assigned to an employee's department instead of keeping a generic default. This ensures department-specific appraisal processes are applied consistently while preserving valid user choices.
Original PR description
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create…
**Problem:** When a template is restricted to a department, appraisals for employees of that department do not use it — a generic (global) template is used instead. **Steps to reproduce:** 1. Create an appraisal template and restrict it to a department. 2. Make sure at least one global (no department) template also exists. 3. Open a new appraisal and select an employee of that department. 4. Observe the appraisal template stays on the global one. **Current behavior:** The global template that was auto-selected before an employee was chosen is kept, ignoring the department-restricted template. **Expected behavior:** The template restricted to the employee's department is selected. **Cause of the issue:** On a new appraisal the template is computed before an employee (and therefore a department) is set, so a global template is pre-selected. When the employee is then chosen, `_compute_appraisal_template` reruns but the `appraisal.appraisal_template_id or ...` clause short-circuits on the already set global template and never falls through to the department's template. **Fix:** Evaluating the department's template before the existing value ensures a department-restricted template takes precedence over a template that was only auto-selected as a default. The existing value is still preserved when the department has no template of its own, so deliberate choices are untouched. opw-6293936 Forward-Port-Of: odoo/enterprise#121377
This fixes a timing issue where financial reports could briefly show an older selected view while a newer selection was still loading. Users now see report results that match their latest choice, reducing confusion when switching report groupings or filters quickly.
Original PR description
Previously, when a report was loading if a variant was selected, it would display the first one when it loaded and display the second one when it loaded. With this, we wont show the first one as we…
Previously, when a report was loading if a variant was selected, it would display the first one when it loaded and display the second one when it loaded. With this, we wont show the first one as we are waiting for the new one. To reproduce: - load the Demo data on the demo company - Add time.sleep(5) in _get_lines - load the Generic Tax report and wait for it to load - click on the Group by: Account > Tax and wait for 3s - click on the Group by: Tax > Account - Watch the Account > Tax load and still being displayed for 3s while the Tax > Account variant is loading. The loading of the report contains 2 steps: - Loading the options of the report - Loading the content of the report itself The options are used to update the bar at the top of the screen with the filters, such as date or horizontal_split. Since some of those filters dont need to call again for the options, we will store them in a map loadingOptionsFunctions, for them to be called when the options have been fetched. If they are clicked when the data of the report is loading, we can directly updated the options since they dont need to update the value of the lines. Some need to update the lines like rounding_unit, however since the call to format_column_values_from_client is faster than querying again the line, We check if the currency changed while loading the report and if it did, we format the column values. Following those changes, a lot of async/await were rendered useless since we are not waiting for the click of the filter before the user can click on another one. We are able to remove them and when changing the value of an option with _updateOption or updateOption, ... they will return the promise of the reloading of the report which can be awaited when necessary.
This fix prevents pay runs from failing when an employee has multiple contract or employment versions within the same month. It ensures payroll processing can continue reliably through the payslip step for Belgian payroll users.
Original PR description
Step to reproduce: 1. Create Employee with multiple version in 1 month 2. Create New PayRun during that month 3. Run the PayRun until Payslip step 4. Expected error on payslip steps reason: substraction of work100_wds and worked_day generate more than 1 value, if we have multiple version in 1 month task-6296276
Opening the manufacturing work order planning Gantt view now works reliably. The change restores required planning data so users can view scheduled work orders without encountering an error.
Original PR description
Issue Before This Commit: ============================= The workorder planning Gantt view only declared some fields inside the popover element. As a result, they were not fetched with the Gantt…
Issue Before This Commit: ============================= The workorder planning Gantt view only declared some fields inside the popover element. As a result, they were not fetched with the Gantt records, even though Gantt decorations also used them. Steps to Reproduce: =================== - Install the **mrp_workorder** module. - Enable the **Work Orders** option in **Manufacturing → Configuration → Settings**. - Create and plan a MO with at least one work order. - Open the work order planning view from the **Planning** menu. - Observe the following error: An `EvalError` is raised: `Name 'has_conflicts' is not defined.` Cause of the Issue: ============================= In this [PR](https://github.com/odoo/enterprise/pull/123693), the variables were moved inside the popover, which caused the Gantt view to lose access to them. After This Commit: ============================= These fields have been restored as top-level Gantt fields, ensuring they are loaded with the record data and accessible wherever they are needed.
The Documents app now keeps the Actions menu working when users select several documents at once. This removes a frustrating blocker where the menu button could appear but not open, while preserving accurate selected-document counts after uploads.
Original PR description
***Issue:*** Since https://github.com/odoo/enterprise/commit/8baaad621a1555680cd77ab514f626137b5b584d the div holding the selection box and the Actions menu carries t-key="targetRecords.length" in…
***Issue:*** Since https://github.com/odoo/enterprise/commit/8baaad621a1555680cd77ab514f626137b5b584d the div holding the selection box and the Actions menu carries t-key="targetRecords.length" in the documents list and kanban views, so every change of the selection count destroys and recreates everything inside it. Ticking a document checkbox updates both the selection and the focused record, and with these two updates the recreation goes wrong: the new ActionMenus component ends up destroyed while its button is still in the page. The dropdown click listeners are removed with the component, so clicking Actions does nothing until the selection changes again. That t-key was added because the selection box shows a stale count after a file upload. The real problem is that SelectionBox caches this.root once in setup. The upload flow reloads the model, which replaces the root record list, and the box keeps counting the selection of the old one. ***Fix:*** Remove the t-key from documents_list_controller.xml and documents_kanban_controller.xml and make DocumentsSelectionBox read the current props.root instead of the value cached by the parent setup. The count follows the new record list after an upload without remounting anything, and the Actions menu is not recreated so its dropdown keeps working. The upload scenario stays covered by the existing multi_view.test.js test, a new test checks that the Actions menu opens with two selected documents. ***Steps to reproduce:*** 1. Open the Documents app 2. Switch to the list view 3. Tick the checkboxes of two documents 4. Click the Actions button next to the "2 selected" box => the Actions dropdown does not open Ticket [link](https://www.odoo.com/odoo/project.task/6365618) opw-6365618 Forward-Port-Of: odoo/enterprise#124238 Forward-Port-Of: odoo/enterprise#123575
Creating Super Accounts in Australian Payroll could fail due to inconsistent internal handling of employee contribution proportions. This fix aligns that handling so payroll administrators can create and view Super Accounts without encountering an error.
Original PR description
Version - 19.0 Steps to reproduce(runbot): - Install `l10n_au_hr_payroll` - Go to Payroll -> Configuration -> Super Accounts - Create a Super Account by filling all the required fields - You will…
Version - 19.0
Steps to reproduce(runbot):
- Install `l10n_au_hr_payroll`
- Go to Payroll -> Configuration -> Super Accounts
- Create a Super Account by filling all the required fields
- You will encounter the issue
**TraceBack:**
```
('hr.menu_hr_employee_payroll', 485, 'Employees > Employees', 756):
Traceback (most recent call last):
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 346, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 377, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 537, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpao31_hxw/migrations/base/tests/test_mock_crawl.py", line 570, in mock_view_form
[data] = record.read(fields_list)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3490, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3747, in _read_format
vals[name] = convert(record[name], record, use_display_name)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 6688, in __getitem__
return self._fields[key].__get__(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1744, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1915, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/19.0/addons/mail/models/mail_thread.py", line 484, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 4954, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/enterprise/19.0/l10n_au_hr_payroll/models/hr_employee.py", line 118, in _compute_proportion_warnings
proportions[emp.id] * 100,
KeyError: 4
```
Issue:
During the refactoring from `read_group()` to `_read_group()`, the `proportions` dictionary became keyed by `hr.employee` records instead of employee IDs. While the condition was updated to use `proportions.get(emp)`, the warning message still accessed the dictionary using `proportions[emp.id]`, resulting in a `KeyError`.
Fix:
Use the employee record consistently when accessing the `proportions` dictionary after switching to `_read_group()`.
Task ID - 6390373
Refrence:
https://github.com/odoo/enterprise/pull/72217/changes#diff-8ae3564d54e47eec919ef273d44f6276d8c6df60e21c5c8c8f7292b1c38cf541R460
Forward-Port-Of: odoo/enterprise#124478This fix prevents users from creating or editing WhatsApp templates from the event communication flow, where choosing the wrong template type could make the event message inaccessible after saving. It keeps other communication types unchanged while respecting WhatsApp template approval constraints.
Original PR description
Issue: User goes to Event.event Form -> communication tab -> add line Select whatsapp -> type something -> create and edit -> create new template with any model event.registration -> save ( all the way including the event form) reload page -> whatsapp event.mail displays "User does not have access to this record". Fix: add a patch to the js get m2oProps to deactivate edit, and create on the prop. WA Templates need more limitations for creation and edits due to the approval process from META's external API. We cannot block the full creation and edit in the xml becuase other event.mail types rely on that flow to create their types like social posts. This was a fix implemented due to needing to revert the oginal fix odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b opw-6334168 Forward-Port-Of: odoo/enterprise#124156 Forward-Port-Of: odoo/enterprise#121852
Email links for appointments now use the website tied to the appointment setup instead of falling back to whichever website last updated the system base URL. This prevents customers in multi-website environments from being sent to the wrong site when managing their appointment.
Original PR description
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from…
In Multiwebsite settings, when the public user interactions needs email generation (appointment or event flow), the email links are generated with a base url that does not corresponds to the one from which the request started. Case 1: - Have website A and website B - Create an appointment page website A - Log in via website B - As public user, make an appointment in Website A - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the appointment. This occurs because when an user log in, the system parameter 'web.base_url' is updated with the current url. This parameter is then used as fallback when we need to retrieve the base url without an active record Case 2: - Have website A and website B - Create an event and assign it to website B - As public user, access the event and register to it - Check the generated email Issue: button links in the email will redirect to the wrong website, so users will encounter an issue when managing the event. This occurs because the record `event.registration` has no website_id field and the base url is taken from the company default website (website A) Backport with improvements of 15bae202d8f1b5bf70bbc63b2d89025e9237e6cf opw-4146760 opw-4336369 Forward-Port-Of: odoo/enterprise#124714 Forward-Port-Of: odoo/enterprise#122669