Monday, September 14, 2026
18 changes · 19.0
Resolved issues and error corrections
This fix prevents customers from using on-site payment in delivery and store pickup flows when gift cards or eWallets are involved in unsupported situations. It helps avoid checkout scenarios that the business does not support, reducing payment errors and customer service issues.
Original PR description
We don't want to support gift cards and eWallets in certain conditions opw-6483282 Forward-Port-Of: odoo/odoo#286946
Website editors can now clear an embedded code snippet and save it without the previous content coming back after reload. This restores the expected behavior and avoids accidentally showing outdated embedded content on website pages.
Original PR description
Scenario: - drop embedded code snippet - edit it to add a value - edit it to put it empty - save Result: on reload the embed is not removed and the old value is restored In 18.2, setting it empty would work and you would see an info alert: "Your Embed Code snippet doesn't have anything to display. Click on Edit to modify it." Fix: delete the embed field if it is saved empty. opw-5454289
Fixes an issue where editing component lines during subcontracting production could leave unused inventory records behind. This prevents later stock reservation and transfer validation errors, helping keep subcontracting inventory data consistent.
Original PR description
#### Issue When manually adding component lines in the subcontracting Record Production flow, extra stock move lines can remain in the database without a linked stock move. Those lines have no…
#### Issue When manually adding component lines in the subcontracting Record Production flow, extra stock move lines can remain in the database without a linked stock move. Those lines have no move_id, so their related state is empty. They can later be selected by stock reservation code and cause validation errors when processing the transfer. #### Steps to reproduce 1. Create a subcontracted product. 2. Confirm a subcontracting receipt/purchase flow for that product. 3. Open the subcontracting Record Production popup. 4. Remove an existing component line. 5. Add a new component line for another storable product available at the subcontractor location. 6. Save/record the production. 7. Check stock.move.line records , Inventory > History > Group By Status. An extra stock move line is left with no move_id. #### Root cause The inverse of `mrp.production.move_line_raw_ids` already collects and deletes move lines detached from existing raw moves. However, when the user adds a new component product, the inverse creates a new additional raw move. Creating that raw move can also create reserved move lines. The inverse then replaces `move.move_line_ids` with the user-entered lines, but it did not collect the newly created reserved lines before replacing them. Those reserved lines were detached from the move and left in the database as orphan stock move lines. #### Fix Apply the same cleanup logic to newly created additional raw moves: collect their auto-created move lines before replacing `move_line_ids`, then unlink those detached lines at the end of the inverse. opw-6304649 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276235
The Barcode app now avoids running the same stock transfer completion step twice when a user exits after making changes. This reduces the risk of creating duplicate backorder moves and helps keep warehouse operations accurate.
Accounting users in Chilean companies can now upload XML files to create customer invoices without needing administrator rights. This prevents invoices from being created without processing the XML details, reducing manual follow-up and errors.
Original PR description
Scenario: - be not an admin but have access to accounting - switch to chilean company - go to customer invoices - click on Upload and upload an XML file Result: an invoice is created, but the XML is not treated because of this permission error: 19.0/l10n_cl_edi/…/account_move.py", line 1078, in _l10n_cl_import_dte invoice.l10n_cl_dte_file = file_data['attachment'] odoo.exceptions.AccessError: You do not have enough rights to access the field "l10n_cl_dte_file" on Journal Entry (account.move). Please contact your system administrator Cause: l10n_cl_dte_file field is only accessible to administrator. opw-6509550
Peruvian sales and purchase ledgers now exclude ISC tax lines from taxable base columns, preventing ISC from being counted twice. This keeps PLE ledger values aligned with electronic invoices sent to SUNAT and improves tax reporting accuracy for affected documents.
Original PR description
When a tax affects the base of the subsequent ones — `include_base_amount`, which is how the ISC is set up in Peru — Odoo links the tax line it generates to those subsequent taxes, so the ISC tax…
When a tax affects the base of the subsequent ones — `include_base_amount`, which is how the ISC is set up in Peru — Odoo links the tax line it generates to those subsequent taxes, so the ISC tax line ends up carrying the IGV in its `tax_ids` (`account/models/account_tax.py`, `tax_data['taxes'] |= subsequent_taxes`). The PLE ledgers build their base columns by summing every move line related to a given tax group, so that ISC tax line was added to `base_igv` as well and the ISC ended up reported twice: once inside the taxable base and once in its own column. A line of 1000.00 with 100.00 of ISC and 198.00 of IGV was declared with a base of 1100.00 instead of 1000.00. `l10n_pe_edi` already subtracts the ISC from the `cbc:TaxableAmount` of the CPE sent to SUNAT, so the electronic invoice and the ledger disagreed on the very same document. ### What changed The base taxes are now joined only for base lines, instead of repeating the condition on each of the twelve `base_*` columns. Besides keeping tax lines out of the base columns, this also stops a tax line from being counted once per subsequent tax: an ISC followed by both the IGV and the 3% withholding produced two rows in the join, and its own column was reported twice. ### Scope `_get_ple_report_data` is shared, so this covers the sales ledger 14.1 and the purchase ledgers 8.1 and 8.2. A configuration where no tax affects the base of a later one is unaffected: the standard Peruvian chart template has no purchase ISC, so ordinary IGV-only purchases report exactly the same values as before. ### Tests - `test_sale_report_isc_base`: an ISC preceding the IGV, on an invoice and on a credit note; the base column excludes the ISC. - `test_sale_report_isc_reported_once`: an ISC followed by the IGV and the 3% withholding is reported once. Both fail without the fix.
Australian payroll now defaults casual employees to the regular casual tax treatment instead of daily casual when appropriate. This helps ensure employees can have student loan withholding applied correctly and reduces payroll setup errors.
Original PR description
Issue: Odoo doesn't provide tax treatments for Daily casual employee. However, it the employement basis is set as casual, it incorrectly defaults to RDXXXX (which is Daily Casual). This prevents the employee from having student loan withhold. This commit defaults it back to regular casual based on the tax free threshold status. Most common case. Daily casual case to be handled in Master. task - 6387496
List view columns can now be resized reliably on tablets and other touch-screen devices. This prevents touch gestures from interrupting the resize action, making list views easier to adjust for users working on mobile hardware.
Original PR description
Steps to reproduce ================== - Use a tablet (touch screen) - Open any list view - Try to resize a column by dragging the column header's right edge => The resize doesn't work properly: it gets interrupted an we can only move a few pixels at a time Cause of the issue ================== The resize handle relies on pointerdown/pointermove/pointerup to run and stop the drag, but nothing tells the browser to opt out of its native touch gestures. On a tablet, the drag can get hijacked as a page scroll, which fires pointercancel instead of pointerup. That event was not listened to, leaving the pointermove handler attached and the resize state stuck. Solution ======== - Set touch-action: none on the resize handle so a touch drag isn't interpreted as scrolling - Listen to pointercancel to properly stop the resize when the browser takes over the gesture anyway
The map view now uses the record limit defined by the action when no specific map limit is set. This makes map behavior consistent with other views, helping users see the expected number of records.
Original PR description
Backport of odoo/enterprise#130336 The map view only considered the `limit` set in the arch, ignoring the one coming from the action (`ir.actions.act_window.limit`), unlike other views (list, kanban) which fall back to it. task-6531776
Website editing color controls and the shop product comparison bar now handle translated or longer labels more reliably. This prevents layout issues and missing styling for users working in languages such as German, improving the experience for multilingual websites.
Original PR description
Steps to reproduce: - Set the user language to German. - Open a color picker with the `Theme` tab in the website editor. - Check the color presets and the reset button. - Open the product comparison bar on the shop page. => Long labels do not fit and some styles are missing. Before this commit, long labels did not fit in the color preset picker. Some CSS selectors also relied on English `title` values, so their styles were not applied in other languages. After this commit, the preset picker adapts to long labels and the CSS selectors use dedicated classes that work in every language. task-6259086
The expense settings now limit selectable company payment methods to appropriate, consistent options. This helps prevent configuration mistakes that could lead to incorrect expense payment setup.
Original PR description
Add domain to company_expense_allowed_payment_method_line_ids field to avoid selecting inconsistent data @Tecnativa TT64416 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures the time off system only processes leave records that are relevant when handling employee contract versions. This helps avoid unnecessary or incorrect processing in multi-contract scenarios, improving reliability for HR operations.
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
The Navarra SII tax agency connection now uses the current web service address after the previous link stopped working. This helps Spanish localization users continue sending tax reporting data to the Navarra authority without connection failures.
Original PR description
The WSDL URL used for the Navarra tax agency SII web service was no longer working. It has been replaced with the updated endpoint 'ssii_1_1'. task-6457647 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285049
This fixes a problem that could block Dutch VAT returns and ICP declarations when companies used a password-protected Digipoort certificate key. The system now reads the key in the expected format, restoring successful submission and status checks.
Original PR description
Steps to reproduce: 1. Set a Digipoort certificate whose private key has a password 2. Submit a VAT return or an ICP declaration 3. It fails with 'bad password read' Analysis: Before 19.0 the PEM key was in an unencrypted format. Since f88f8258ead, env['certificate.key'].pem_key is encrypted whenever the key has a password. Every consumer in this module loads it without a passphrase: the VAT wizard, the ICP wizard and the status polling cron. Same cause as (odoo/enterprise#96562), which fixed it for l10n_mx_edi. Solution: Decrypt the key when reading it, as was already the case before 19.0. opw-6421300
Final invoices now correctly show remaining down payments even when a related credit note was issued. French PDP e-invoicing exports and imports now use the correct document types and references, helping invoices stay compliant and easier to reconcile.
Original PR description
## Bug n°1 (sale) Downpayment lines don't appear on the final invoice, when there is a credit note linked to the downpayment, even if the resulting downpayment is not zero. **STEP TO REPRODUCE** 1.…
## Bug n°1 (sale) Downpayment lines don't appear on the final invoice, when there is a credit note linked to the downpayment, even if the resulting downpayment is not zero. **STEP TO REPRODUCE** 1. Create a SO. 2. Create a downpayment (let's say 100$). 3. On this downpayment create a credit note, and set the downpayment line on the credit note to 50$. 4. Return to the SO, and create the final invoice. 5. On the final invoice, there is no mention of the downpayment and credit note. Expected behavior: The final invoice contains a downpayment line with a unit price of 100$ - 50$ = 50$. **CAUSE** We invoice the downpayment line 1 time for the downpayment, and 1 time for the credit note. This make qty_to_invoice computed on the downpayment line equal to 0, so it's skipped in the final invoice. **FIX** For downpayment line, we ignore the qty_to_invoice, and check if the price_unit of the downpayment line is not 0. If so, we should invoice the downpayment line. For final invoice, the invoiced qty should be -1, and 1 for downpayments and downpayment credit notes. ## Bug n°2 (l10n_fr_pdp) Odoo doesn't correcly handle downpayments when sending invoices using pdp. 1. Because of bug n°1, since downpayment lines don't appear on the final invoice when there is a credit note on the downpayment, the downpayment lines also don't appear in the generated xml. 2. For downpayment, the InvoiceTypeCode should be 386. For credit note of downpayment, the CreditNoteTypeCode should be 503. For the final invoice (invoice done after downpayments), the ProfileID should be B4. 3. On the final invoice, their should be BillingReference for each downpayments and credit note of those downpayments. With a corresponding DocumentTypeCode (386 downpayments, 503 credit notes). On import, there is 2 cases to handles for the final invoice. 1st case: the downpayments lines are present in the final invoice. (already handled by default) 2nd case: the downpayments line are not present in the final invoice. The downpayment amount is in the prepaidAmount node, and all amounts on the xml correspond to the invoice without any downpayments. In the 2nd case, we need to find the downpayments, and copy their lines to the final invoice. **STEP TO REPRODUCE** 1. Create a sale order. 2. Create a downpayment. 3. Create the final invoice and send it via pdp. 5. Inspect the xml and notice the requirements stated previously are not met. opw-6420924 Forward-Port-Of: odoo/odoo#281717
Managers in multi-company setups can now open employee records, organization charts, and expense items without being blocked by access errors from companies they are not allowed to view. Expense team approvers also get smoother handling when creating expenses for their subordinates across company boundaries.
Original PR description
_(updates on July-17th and July-28th for points 2. and 3. in `hr_expense`)_ # Introduction **1\.** A fix to `hr_org_chart` was initially proposed. I think it is mergeable because it fixes the…
_(updates on July-17th and July-28th for points 2. and 3. in `hr_expense`)_ # Introduction **1\.** A fix to `hr_org_chart` was initially proposed. I think it is mergeable because it fixes the user-experience properly like expected in Odoo standard. Other commits are suggested to `hr_expense`. They were designed to allow more flexibility in the management of `hr_employee.company_id` (in multi-company context) and allow not to duplicate the `hr.employee` of each companies of the `res.users`. **2\.** The [FIX] silences a multi-company access error when searching for Expense validators => it seems safe **3\.** The [IMP] largely allow more flexibility for a "Expense: Team Approver" when creating expenses on behalf of its subordinates # 1. in hr_org_chart [FIX] Prevents multi-company error when recursively searching for ancestors. <img width="1035" height="789" alt="image" src="https://github.com/user-attachments/assets/d5517f79-7efc-4223-ae77-0af8b25a3d1e" /> ### Issue description In a multi-company environment, when one of the `hr_employee.company_id` of a hierarchy is not in the allowed companies of a Manager's `res_users.company_ids`, this Manager can view `hr.employee` in the list view but cannot open their forms. This happens when: - `hr_org_chart` module is installed - the Org Chart is displayed on the 1st page of the `hr.employee` form, like when the HR settings "Skills Management" is disabled (in `res.settings`) => thus the whole form becomes inaccessible from the manager When a `hr.employee` form is opened, a multi-company access error is thrown to him, even if the `company_id` of the opened `hr.employee` is in the user's `res_users.company_ids`, because of the hierarchy's `company_id`. It should be expected that the part of the Org Chart which is not allowed to be seen would just be hidden. ### Steps to reproduce Data setup: - Employee "A" in company A - Manager "M" in company A, manager of "Employee A" - Manager of manager "MM" in company A, manager of "Manager M" - And now, in company B (let's say a Holding), the "Director" is manager of "Manager MM" - "Manager M" is only given access access to Company A - the module "hr_org_chart" is installed Actions: - Login with Manager M - Browse to Employees list and try and open the form of "Employee A" (up to tab _"Professional information"_, if it is not the 1st of the notebook) ### Proposed fix This PR re-uses the already existing method `_check_employee` which contains all the logic to solve the issue. Maybe the call to this method was forgotten? This PR simply call this method when finding an ancestor, in the controller of `hr_org_chart`. This fix is thus very limited to the call to the public method `hr_org_chart.get_org_chart()` made by the Org Chart widget. ### Desired behavior after PR is merged The part of the Org Chart not allowed to be seen by "Manager M" is hidden. # 2. hr_expense [FIX] <img width="541" height="415" alt="image" src="https://github.com/user-attachments/assets/d594815b-2b77-4088-878b-9b192b64d6a3" /> ### Issue description As an employee, I click on the button "View Report" on my expense. I get a multi-company access error, preventing me to view and edit my expense report. This is because the manager of the department I belong is in a company I'm not allowed to see. This can also happen just when opening my Expense (instead of Expense Report). ### Current behavior before this PR The employee is blocked to continue editing its Expense or to submit it to a Report. ### Current behavior after this PR The employee can edit and submit its Expense no matter the `company_id` of its hierarchy. Technically: the `can_approve` field on the expense sheet uses a localized `.sudo()` method to bypass multi-company limits when searching if the current user is a validator. # 3. hr_expense [IMP] <img width="1028" height="549" alt="image" src="https://github.com/user-attachments/assets/1096c0d4-d025-46a9-8559-6bab5de71577" /> ### Improvement summary In multi-company environment, allow a "Expense: Team Approver" to create Expenses for its subordinates (`hr_expense.employee_id`) **no matter the `hr_employee.company_id` of its subordinates**. The domain of `hr_expense.employee_id` keeps the security of `check_company=True` => thus the Manager only sees `hr.employee` having their `company_id` in the manager's allowed companies (`res_users.company_ids`). ### Current behavior before this PR Context: a 8-companies environment where the `hr.employee` of each hierarchy chains are splitted in many different companies, like: - top-level (admin board): 1 company - middle management: approx. 2 companies - down level: the other companies The "down level" have `hr.employee` but no `res.users`. The "middle management" have `res.users` and must create the Expenses of their "down level" subordinates on their behalf. Issue: as a manager, as per Odoo proposal, I need to have a `hr.employee` in the same company of my subordinates to be able to create Expense of their behalf. However, this is very inconvenient because as a Manager, I can have employees in various companies. And my own manager it not in the same company than me, so the same issue applies recursively. ### Behavior after this PR is merged The domain of the field `expense_id.employee_id` is more permissive. As a Manager, it allows me to select the Employee I manage in my active company, no matter if I have or not myself a `hr.employee` in this company. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282528 Forward-Port-Of: odoo/odoo#266261
Users can now click and view XML Request and XML Response values on Argentine electronic invoices without triggering an error. This improves reliability when reviewing ARCA invoice details in Odoo.
Original PR description
Currently, an error occurs when clicking the XML Request or XML Response values on an Argentine invoice. **Steps to reproduce:** - Install the `l10n_ar` module and enable developer mode. - Switch to…
Currently, an error occurs when clicking the XML Request or XML Response
values on an Argentine invoice.
**Steps to reproduce:**
- Install the `l10n_ar` module and enable developer mode.
- Switch to the `(AR) Responsable Inscripto` company.
- Create and confirm a new invoice for an `(AR) Exento` customer using
the `Electronic Invoice (FE)` journal and adding an invoice line.
- Open the `ARCA` tab.
- Click on the value of `XML Request` or `XML Response`.
**Error:**
```
TypeError: Cannot read properties of undefined (reading 'fields')
at InvoiceExtractFormRenderer.getBoxType
```
**Root Cause:**
The `l10n_ar_afip_xml_request` and `l10n_ar_afip_xml_response`
fields are text-type fields and are `not relational fields`.
At [1], when these fields gain focus, `getFullFieldName()` can build
a field name such as `l10n_ar_afip_xml_request.null` because the target
does not provide a `data-field` value. Since the resulting field name
contains a dot, `getBoxType()` interprets `l10n_ar_afip_xml_request` as
a parent relational field and tries to access its `_config.fields`.
However, text fields do not have a `_config` attribute (only available with
`StaticList`, which extends `DataPoint`). Consequently, accessing
`_config.fields` on the XML text field results in a `TypeError`.
**Fix:**
This commit prevents the error when accessing XML values, allowing
users to view the XML Request and XML Response without issues.
[1]:
https://github.com/odoo/enterprise/blob/8379522aacc1e81f8418142aa93fbf89b29906e9/iap_extract/static/src/components/manual_correction/form_renderer.js#L357
opw-6547465Validated future time off is now counted when showing an employee’s remaining allocated leave. This prevents balances from appearing too high after future leave has already been approved.
Original PR description
**Steps to reproduce:** - Create and validate an allocation of 10 days. - Take and validate a leave of 5 days in the future. - Issue: the allocation's `virtual_remaining_leaves` still shows 10 instead of 5. **Issue:** `hr.leave.allocation._compute_leaves()` calls `_get_consumed_leaves()` with `ignore_future=True`, which filters the leaves domain to `date_from <= today`. A validated future leave is excluded from the query before it can be deducted, even though the allocation grants its days upfront and isn't gated by any accrual plan. This flag was intentionally dropped from this call by (odoo/odoo#193685), then came back by accident via a forward-port of (odoo/odoo#249441). **Solution:** Drop `ignore_future=True` from `_compute_leaves()` Task-6534125