Daily updates from Odoo
Wednesday, July 22, 2026
35 changes · saas-19.2
Enhancements to existing features
The Nilvera client returns base64-encoded PDF content from the GET pdf endpoint. A previous change https://github.com/odoo-dev/odoo/commit/d2c2dc0bc33c369369ba748a513fad0c6edcaf6a incorrectly stored this base64 string directly into the `ir.attachment.raw` field without decoding. Because the field is binary, the base64 ASCII text was UTF-8 encoded on the disk, leaving the files unreadable in browsers. This commit introduces a migration script to fix this. For newly downloaded attachment
Original PR description
The Nilvera client returns base64-encoded PDF content from the GET pdf endpoint. A previous change https://github.com/odoo-dev/odoo/commit/d2c2dc0bc33c369369ba748a513fad0c6edcaf6a incorrectly stored this base64 string directly into the `ir.attachment.raw` field without decoding. Because the field is binary, the base64 ASCII text was UTF-8 encoded on the disk, leaving the files unreadable in browsers. This commit introduces a migration script to fix this. For newly downloaded attachments, 35fd6ce handles the decoding. task-6377121 Forward-Port-Of: odoo/odoo#275376
Resolved issues and error corrections
This fix prevents users from creating or editing WhatsApp templates from the event communication setup, avoiding templates being linked to the wrong type of event record. It helps prevent access errors after saving and reloading an event, while preserving the normal creation flow for other communication types.
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
The report page layout has been adjusted so the chatter panel remains visible on the right side of the screen even when a report is very wide. Users can now read or add messages without needing to scroll horizontally across large reports.
Original PR description
Issue: - When reports are large/wide, the chatter component is pushed beyond the visible viewport, appearing only at the absolute right edge of the overflowing report rather than the right edge of the screen. Fix: - Updated the layout container to prevent the chatter from shrinking or overflowing with the report block, ensuring the main report scrolls independently while the chatter stays pinned to the screen viewport. Impact: - Keeps the chatter panel fully visible on the right side of the screen, allowing users to communicate without scrolling horizontally on wide reports. task-[6376792](https://www.odoo.com/odoo/project/967/tasks/6376792) Forward-Port-Of: odoo/enterprise#123734
This update registers the WhatsApp Identifiers translation template so translation tools can process it correctly. It helps ensure labels and messages from this area can be translated consistently across languages.
Original PR description
pot files must be registered there. See 9966b160972a053e051f2213846acc64d133f2a3 Forward-Port-Of: odoo/enterprise#124076 Forward-Port-Of: odoo/enterprise#124026
This fix ensures Belgian payroll calculates leave duration consistently for employees on credit time. It prevents similar work schedules from producing different leave counts, improving payroll accuracy and reducing manual corrections.
Original PR description
Purpose: For credit time Employees, similar configurations of calendar lead to different duration counts Cause: leave duration is dependant on average hours per day of the calendar (which changes with configuration as credit time is considered as absense) to decide if the duration is half or full day - added override for the introduced `_get_worked_days_and_hours` to recompute the number of days as a ratio between actual worked hours (excluding credit time) and total hours of specified in the calendar (including credit time) task-id: 6212942
The appointment link copy confirmation now appears only after the clipboard action is actually completed. This prevents automated appointment CRM checks from moving too early, making the feature more reliable across browsers and system load conditions.
Original PR description
Prior to this commit, the success notification for copying an appointment link to the clipboard was triggered synchronously, while the actual `navigator.clipboard.writeText` execution was deferred inside a `setTimeout`. This caused a race condition (depending on the browser's cpu load) during tours (e.g., `appointment_crm_meeting_tour`). The tour would proceed and restore the mocked clipboard object (`oldWriteText`) before the deferred `setTimeout` block had a chance to execute. This commit fixes the issue by moving the notification logic inside the `setTimeout` callback. The tour is also updated to wait explicitly for the success notification before cleaning up the clipboard mock and proceeding to discard the slots. runbot-241004
Envia shipping quotes now correctly include selected insurance coverage when calculating rates. This ensures businesses see accurate delivery costs before confirming sales orders, avoiding underquoted shipping charges.
Original PR description
Issue ----- Insurance request is not reflected on the rating given by Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - Create a MX client - Create a product (with some weight) - Create a SO - Add the product - Add envia delivery and get a rate - Update Envia delivery method - Set insurance to 50% - Go back to the SO - Add envia delivery and get a rate > The rate is the same both times Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment Follow up of 7258e4a ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#124700
The point of sale barcode lookup flow now checks product creation permissions in a more reliable way. This helps ensure users only see or use product creation options when they have the right access, avoiding inconsistent behavior at checkout.
Original PR description
Replace the asynchronous `allowProductCreation` method with the `hasProductCreationAccess` getter to evaluate product creation permissions synchronously and ensure consistent behavior. Task-6361787 Related PR: https://github.com/odoo/odoo/pull/274420 Forward-Port-Of: odoo/enterprise#125036 Forward-Port-Of: odoo/enterprise#123073
Bank reconciliation now shows the same supporting attachments in the list view as in the kanban view. This prevents users from missing documents when reviewing or matching bank transactions, making reconciliation more consistent.
Original PR description
The aim of this commit is showing the same attachment in the bank reconciliation list view than in the kanban view. Before this commit, the field used to display the attachments was attachment_ids, this field were a related on the attachment_ids from account.move. This fix, removes the related to only keep a domain on the One2Many field. Thanks to the relational database, Odoo is giving us the right attachments when we want to display the field. task-6153002 Forward-Port-Of: odoo/enterprise#117245
Sales commission achievement records with very large identifiers can now be opened without triggering a misleading “record does not exist” message. This ensures users can reliably access commission achievement details even when record numbers exceed browser number limits.
Original PR description
Steps to reproduce: - Open an achievement with id > JS limit Issues: - We get a pop-up saying the record does not exists The reason we get this error is because since we are browsing a record with an id greater than JS limit the browser truncate it. In order to solve this issue the following PR was made #108751. A field `id_str` was added but it still wasn't working as we weren't retrieving the `id_str`. We now do this by passing `id_str` in the context and retrieving it on the `web_read`. Forward-Port-Of: odoo/enterprise#113701
This fix prevents database upgrades from failing when a predefined Human Resources document folder was previously deleted or disabled. The system now skips unavailable employee folders when adding the Sign action, allowing upgrades to complete normally.
Original PR description
Steps to reproduce: 1 Install documents_hr and hr_sign on saas-19.1. 2 Go to Settings → Documents → disable Human Resources. 3 Open the Documents app and delete the Employees - My Company folder. 4…
Steps to reproduce:
1 Install documents_hr and hr_sign on saas-19.1.
2 Go to Settings → Documents → disable Human Resources.
3 Open the Documents app and delete the Employees - My Company folder.
4 Upgrade the database to saas-19.2.
Issue:
- During the upgrade, the post-init hook attempts to embed the HR Sign action into predefined document folders. Since the Employees - My Company folder has been deleted (or is inactive), the folder lookup returns no record, leading to the following error:
```python3
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-19.2/odoo/service/server.py", line 1664, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/func.py", line 65, in locked
return func(inst, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/registry.py", line 186, in new
load_modules(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 465, in load_modules
load_module_graph(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 244, in load_module_graph
getattr(py_module, post_init)(env)
File "/home/odoo/src/enterprise/saas-19.2/documents_hr_sign/__init__.py", line 12, in _embed_sign_post_init
folders.with_user(SUPERUSER_ID)._embed_action(sign_action.id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1643, in _embed_action
folder.action_folder_embed_action(folder.id, action_id)
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1614, in action_folder_embed_action
return self.get_documents_actions(folder_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/documents/models/documents_document.py", line 1522, in get_documents_actions
raise UserError(_('This folder does not exist or is not accessible.'))
odoo.exceptions.UserError: Esta carpeta no existe o no es accesible.
```
Root cause:
- As part of documents_sign, the documents_hr_sign action is embedded into predefined document folders (introduced in https://github.com/odoo/enterprise/pull/101890).
- The folder lookup relies on [_search()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L4681-L4691), which filters out inactive records
through the active test. Consequently, [search_fetch()](https://github.com/odoo/odoo/blob/85992d5f5f8caeacdcc570fb9fefb4cfcec6460c/odoo/orm/models.py#L1441-L1451) returns no matching
folder when the predefined folder has been deleted or deactivated. It will
try to get document actions of predefined folder here, so if the folder is
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1592
inactive it will not be able to read the folder here.
https://github.com/odoo/enterprise/blob/6d334a17d10faec33d60f4a8d7d263c091bb456e/documents/models/documents_document.py#L1494
Fix:
- Instead of attempting to embed the Sign action into all company employee folders, filter out inactive folders before calling _embed_action().
- This ensures the post-init hook only processes active employee document folders. If a predefined folder has been deleted or deactivated, it is skipped preventing the upgrade from attempting to embed an action into an inaccessible folder and avoiding the resulting UserError.
opw-6358063
upg-4449902Creating or viewing Super Accounts in Australian Payroll could fail because the system used inconsistent references when checking employee super contribution proportions. This fix makes the reference consistent, preventing the error and allowing payroll configuration to continue normally.
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#124478Emails generated from appointment flows now use the website address tied to the appointment setup instead of falling back to the last login or default website address. This prevents customers on multi-website setups from being sent to the wrong site when managing their bookings.
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
Spanish VAT books now report the correct tax amounts for vendor bills using taxes with negative components, such as certain EU tax scenarios. This prevents valid tax amounts from appearing as zero, improving the accuracy of VAT reporting for Spanish companies.
Original PR description
Problem: In the Spanish VAT books, taxes with negative component (like 21% EU G) always show their amounts as zero. Steps to reproduce: 1. Install the l10n_es_reports module and select the Spanish company 2. Create a vendor bill with a vendor from another EU country and add a product 3. Make sure the tax applied to the product has a negative component (like 21% EU G) 4. Confirm the bill 5. Go to Accounting > Reporting > Tax Return 6. Generate the VAT books from the action menu and check the tax amounts 7. Notice how the tax amount is zero, even though the tax was applied to the bill Cause: When calculating the tax amounts, the negative component cancels out the positive component, leading to the amount always showing as zero in the VAT books. opw-6169766 Forward-Port-Of: odoo/enterprise#124030 Forward-Port-Of: odoo/enterprise#123738
This update removes an outdated customization that referenced a receipt section no longer present in Point of Sale. It helps keep Belgian certified POS receipts working correctly after the standard tax summary layout was restored.
Original PR description
In the community point_of_sale module, the `<t id="tax_base">` element was removed from the order receipt template in order to restore the 19.0 tax summary design (always displaying the tax base). Remove the xpath in pos_blackbox_be that was targeting this deleted element. task-id: 6296906 Forward-Port-Of: odoo/enterprise#120972
Mexican payroll now calculates expected work hours correctly even before a payslip has been created. This prevents off-cycle payroll runs from under-calculating wages due to missing draft payslip data.
Original PR description
### Description of the issue/feature this PR addresses: This PR addresses an issue where expected Mexican work hours and attendance fields fail to generate correctly in contexts where a draft payslip…
### Description of the issue/feature this PR addresses: This PR addresses an issue where expected Mexican work hours and attendance fields fail to generate correctly in contexts where a draft payslip does not yet exist. Specifically, this was preventing the correct evaluation of work hours when an off-cycle payslip is initially generated for a given time period. ### Current behavior before PR: The _preprocess_work_hours_data method aborts early if no hr.payslip record is found for the period. Because the method relies on an instantiated payslip to fetch calendar info, duration validation, and rule parameters, work hours cannot be properly calculated during the initial generation of off-cycle payslips. As a result, off-cycle payslips will under-calculate the total wage for a given pay period. ### Desired behavior after PR is merged: The strict dependency on the payslip record is removed. If a payslip is absent, the logic will now safely fall back to the contract version's base data: - The calendar defaults to the contract version's resource_calendar_id. - The duration falls back to standard (is_wrong_duration = False). - The l10n_mx_schedule_table rule parameter is fetched globally from the environment (hr.rule.parameter) instead of using the payslip helper. This ensures that expected work hours are calculated consistently across all payroll workflows, even before the payslip is fully instantiated. opw-6351402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Appraisals now prioritize the template assigned to an employee's department instead of keeping a generic default. This helps HR teams use the right review form automatically while preserving valid manual template 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
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able
Original PR description
Before this commit, two issues affected custom snippet saves. First, the new builder allowed saving the Alternative Products block from product pages as a custom snippet. This block is generated from the current product alternatives, so it is page-specific content. Second, a block saved as a custom snippet could keep `oe_unremovable` or `oe_unmovable` on its root. A saved custom snippet is meant to become a normal reusable block. Once the user drops it on another page, they should be able to remove it or move it like any other block. After this commit, builder plugins can declare selectors that cannot be saved as custom snippets, and `website_sale` uses this to exclude the Alternative Products block. The saved copy also drops `oe_unremovable` and `oe_unmovable` on its root before calling `ir.ui.view.save_snippet`. task-6296872 Forward-Port-Of: odoo/odoo#277092 Forward-Port-Of: odoo/odoo#275303
When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be greater than the number of invoices. In this case, we use <hX> tags to split invoices: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/odoo/addons/base/models/ir_actions_report.py#L916-L923 This tag is added for PDF files, using the invoice's title: https://g
Original PR description
When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be…
When sending a batch of invoice, we first generate an unique PDF file regrouping every invoice. When at least one invoice needs more than one page to be rendered entirely, the number of pages will be greater than the number of invoices. In this case, we use <hX> tags to split invoices: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/odoo/addons/base/models/ir_actions_report.py#L916-L923 This tag is added for PDF files, using the invoice's title: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/addons/web/views/report_templates.xml#L627 In some localization modules, this title shouldn't be displayed and it is removed. Example for Chile: https://github.com/odoo/odoo/blob/5ba945cdba6be3ff8838e56784ade16c6200de84/addons/l10n_cl/views/report_invoice.xml#L149 In this case, no `<h3>` tag will be added and an error is raised as we cannot separate invoices. We propose to add an empty `<h3>` tag if the document title is not defined. opw-6281187 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277131 Forward-Port-Of: odoo/odoo#269100
Purpose: For credit time Employees, similar configurations of calendar lead to different duration counts Cause: leave duration is dependant on average hours per day of the calendar (which changes with configuration as credit time is considered as absense) to decide if the duration is half or full day - added a context flag `compute_leave_duration` to be accessed in `_work_intervals_batch` so we consider credit time intervals for leave duration computation - extracted some logic from `_get
Original PR description
Purpose: For credit time Employees, similar configurations of calendar lead to different duration counts Cause: leave duration is dependant on average hours per day of the calendar (which changes with configuration as credit time is considered as absense) to decide if the duration is half or full day - added a context flag `compute_leave_duration` to be accessed in `_work_intervals_batch` so we consider credit time intervals for leave duration computation - extracted some logic from `_get_durations`to `_get_worked_days_and_hours` to be overriden in be localization for credit time attendances task-id: 6212942 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277347 Forward-Port-Of: odoo/odoo#273958
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing t
Original PR description
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ###…
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing technical name and message as the traceback when `stack` is absent. A focused regression test covers an `AbortError`-like object without `stack`. ### Tests - `git diff --check` - `node --check addons/web/static/src/core/errors/error_utils.js` - `node --check addons/web/static/tests/core/errors/error_service.test.js` - `@web/core/errors` HOOT suite: 24 tests, 107 assertions passed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr. Forward-Port-Of: odoo/odoo#276864
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Original PR description
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References:
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs Forward-Port-Of: odoo/odoo#275893 Forward-Port-Of: odoo/odoo#275367
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 Forward-Port-Of: odoo/odoo#276356 Forward-Port-Of: odoo/odoo#273905
Original PR description
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 Forward-Port-Of: odoo/odoo#276356 Forward-Port-Of: odoo/odoo#273905
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynch
Original PR description
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynchronous permission check with a getter that evaluates product creation rights. - Cache the group access information in `posService` and let the hr override use the getter. Task-6361787 Related PR: https://github.com/odoo/enterprise/pull/123073 Forward-Port-Of: odoo/odoo#277578 Forward-Port-Of: odoo/odoo#274420
Steps to reproduce: 1. Drop the Website Form snippet. 2. Add a checkbox field. 3. Change the label position to Top. > The Default Value option disappears. Cause: The `applyTo` selector relied on the `.col-sm` wrapper, which is only present for left/right label positions. As a result, it did not match checkbox fields with Top or None labels. This commit fix the applyTo selector so the Default Value option is displayed for checkbox fields regardless of the selected label position.
Original PR description
Steps to reproduce: 1. Drop the Website Form snippet. 2. Add a checkbox field. 3. Change the label position to Top. > The Default Value option disappears. Cause: The `applyTo` selector relied on the `.col-sm` wrapper, which is only present for left/right label positions. As a result, it did not match checkbox fields with Top or None labels. This commit fix the applyTo selector so the Default Value option is displayed for checkbox fields regardless of the selected label position. task-6373796 Forward-Port-Of: odoo/odoo#277380 Forward-Port-Of: odoo/odoo#275823
v19 WIoT Boxes will be listening on localhost when updating to v19.1+, we need to ensure they use `http_interface = 0.0.0.0` after the update. Forward-Port-Of: odoo/odoo#272063
Original PR description
v19 WIoT Boxes will be listening on localhost when updating to v19.1+, we need to ensure they use `http_interface = 0.0.0.0` after the update. Forward-Port-Of: odoo/odoo#272063
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2
Original PR description
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are…
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2 Dozen of the product and select the carrier on the transfer The 24 kg shipment is weighed as 2 kg, so the carrier is proposed on the transfer although it exceeds its maximum weight, and it is correctly refused on a sale order for the same quantity. With a unit smaller than the reference one, valid carriers are hidden instead. Solution: Use the quantity in the reference unit of the product, as done for sale orders and everywhere else the shipment weight is computed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277425
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. - 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
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 which the request started. - 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) opw-4146760 opw-4336369 Forward-Port-Of: odoo/odoo#276984 Forward-Port-Of: odoo/odoo#274051
### [FIX] web: fix mocked dates in tests Dates are mocked in all unit tests by default; either to a default static value, or to one defined in the test/suite. To do so, the `window.Date` constructor is overridden to have the arguments auto-filled with the current mock date paramters. Before this commit, an additional offset was always added to the given arguments to reflect: - the time elapsed from the beginning of the test; - any virtual offset added by a helper such as 'advanceTime
Original PR description
### [FIX] web: fix mocked dates in tests Dates are mocked in all unit tests by default; either to a default static value, or to one defined in the test/suite. To do so, the `window.Date` constructor…
### [FIX] web: fix mocked dates in tests Dates are mocked in all unit tests by default; either to a default static value, or to one defined in the test/suite. To do so, the `window.Date` constructor is overridden to have the arguments auto-filled with the current mock date paramters. Before this commit, an additional offset was always added to the given arguments to reflect: - the time elapsed from the beginning of the test; - any virtual offset added by a helper such as 'advanceTime'. The issue is that the spec of the Date constructor wants that the returned date object has to match all given arguments, and any omitted argument will be defaulted to the current date/time. This was not the case in tests, as the offset was always added, regardless of the given arguments. With this commit: only the arguments that are NOT given and that have been defaulted to current (mocked) date/time will be offset by the adequate value. Furthermore: as these mocked parameters are meant to reflect UTC values, the offset now also considers the *actual* browser offset to generate a local date from the mock date parameters. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277041 Forward-Port-Of: odoo/odoo#275391
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure t
Original PR description
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027.…
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure the certificate for Ticketbai works) 3. Go to Settings → Spain Localization → set Tax Agency for = Bizkaia 4. Change VAT number for customer Mulhacén Digital S.L. into N0011452J (must be a foreign entity ID) 5. Go to Settings > Technical > System Parameters and set the parameter 'l10n_es_edi_tbai.epigrafe' to 165360 6. Create a new invoice for that client and try to send it to TicketBAI 7. Error: B4_1000002: Todos los registros incluidos en la petición son incorrectos. B4_2000027: La factura contiene un Tipo de desglose incorrecto. Ha de ser a nivel de operación cuando la factura es completa y, además, existe destinatario extranjero (tipo IDOtro o que sea NIF que empiece por N) o la Clave de IVA es 02. ### Cause of the issue: The _l10n_es_is_foreign() method evaluated these customers as domestic because their country was set to Spain and their VAT did not start with "ESN". It failed to recognize a standalone "N" prefix as a valid foreign identifier. https://github.com/odoo/odoo/blob/75ae45861e2f417aa2b90bdb2b2869718e091c09/addons/l10n_es/models/res_partner.py#L7-L10 ### Reason to introduce the fix: Adding the 'N' prefix to the _l10n_es_is_foreign() check ensures the system correctly treats these entities as foreign for tax purposes. This generates the correct XML structure automatically, without forcing users to unnaturally prepend "ES" to a legally valid NIF. opw-6326359 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275231
When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354 Forward-Port-Of: odoo/odoo#272472
Original PR description
When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354 Forward-Port-Of: odoo/odoo#272472
Currently, we only load the XML data from the exported POS order in the field `l10n_jo_edi_pos_computed_xml` when`l10n_jo_edi_pos_error` is False. It should be the opposite. The field `l10n_jo_edi_pos_computed_xml` is only used when we call `download_l10n_jo_edi_pos_computed_xml()` from the anchor "Download XML" , and that anchor is only visible when `l10n_jo_edi_pos_error` is True. If the request succeeds, then the XML file will be stored in the field `l10n_jo_edi_pos_xml_attachment_i
Original PR description
Currently, we only load the XML data from the exported POS order in the field `l10n_jo_edi_pos_computed_xml` when`l10n_jo_edi_pos_error` is False. It should be the opposite. The field `l10n_jo_edi_pos_computed_xml` is only used when we call `download_l10n_jo_edi_pos_computed_xml()` from the anchor "Download XML" , and that anchor is only visible when `l10n_jo_edi_pos_error` is True. If the request succeeds, then the XML file will be stored in the field `l10n_jo_edi_pos_xml_attachment_id` anyway. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276918
Miscellaneous changes
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation
Original PR description
Issue: User goes to Event.event Form -> communication tab -> add line - can no longer create a social post in template communication tab Fix: remove "no_create_edit: True" to the associated field in the xml to unblock creation of new mail.templates Reverted from commit (odoo/odoo@f58e9f97192ac0ff8d159377494d6c68f871d20b) due to not being able to make social media posts on event communication tab. I originanlly suggested this change because WA Templates need more limitations for creation and edits. This then blocked other creation and edits that rely on this flow. opw-6334168 Forward-Port-Of: odoo/odoo#276031 Forward-Port-Of: odoo/odoo#272262