Thursday, March 19, 2026
16 changes · saas-18.4
Resolved issues and error corrections
This fix prevents Vietnamese Viettel Sinvoice submissions from failing when invoices include global discounts or down payment deductions. It also ensures invoice note lines are included and corrects a Vietnamese accounting default for work-in-progress production accounts.
Original PR description
Previously, the invoice logic did not properly handle the following scenarios: - Global discount: when a global discount was applied, negative values were sent to Sinvoice, resulting in a BAD_REQUEST_ITEM_VALUES_NEGATIVE error. - Down payment: when an invoice included a down payment to deduct the amount, negative values were sent to Sinvoice, triggering the same BAD_REQUEST_ITEM_VALUES_NEGATIVE error. - Note lines: note lines on the invoice were not being uploaded/included in the invoice submission. This commit fixes the handling of global discounts and down payments by ensuring negative values are properly transformed before being sent to Sinvoice, and adds support for uploading note lines in the invoice. task-5875158 Forward-Port-Of: odoo/odoo#254265 Forward-Port-Of: odoo/odoo#251913
The stock module now handles very large groups of related deliveries more efficiently. This prevents memory-related crashes when opening or calculating delivery information for products with complex lot histories, improving reliability for warehouses with high-volume operations.
Original PR description
- Some lots were found to contain very large delivery sets (7k+ picking IDs) with multiple parents. - Updating parent sets in a single operation caused a MemoryError for large datasets. ```sql…
- Some lots were found to contain very large delivery sets (7k+ picking IDs) with multiple parents.
- Updating parent sets in a single operation caused a MemoryError for large datasets.
```sql
Traceback (most recent call last):
File "/tmp/tmpe5fq5baf/migrations/base/tests/test_mock_crawl.py", line 333, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpe5fq5baf/migrations/base/tests/test_mock_crawl.py", line 346, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpe5fq5baf/migrations/base/tests/test_mock_crawl.py", line 506, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpe5fq5baf/migrations/base/tests/test_mock_crawl.py", line 539, in mock_view_form
[data] = record.read(fields_list)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 3858, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 4089, in _read_format
vals[name] = convert(record[name], record, use_display_name)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 7078, in __getitem__
return self._fields[key].__get__(self)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 1311, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 1493, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/18.0/addons/mail/models/mail_thread.py", line 442, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5297, in _compute_field_value
fields.determine(field.compute, self)
File "/home/odoo/src/odoo/18.0/odoo/fields.py", line 110, in determine
return needle(*args)
File "/home/odoo/src/odoo/18.0/addons/stock/models/stock_lot.py", line 149, in _compute_delivery_ids
delivery_ids_by_lot = self._find_delivery_ids_by_lot_iterative()
File "/home/odoo/src/odoo/18.0/addons/stock/models/stock_lot.py", line 385, in _find_delivery_ids_by_lot_iterative
delivery_by_lot[parent_id].update(delivery_by_lot[lot_id])
MemoryError
(Pdb)len(all_lot_ids)
22166
(Pdb)len(barren_lines)
9682
(Pdb)len(lots_to_propagate)
9682
Lot_id 11412: delivery_by_lot size = 7420, parents = 3
Lot_id 11753: delivery_by_lot size = 0, parents = 7
Lot_id 12845: delivery_by_lot size = 11, parents = 5
Lot_id 14646: delivery_by_lot size = 12, parents = 2
Lot_id 15801: delivery_by_lot size = 1700, parents = 3
Lot_id 19817: delivery_by_lot size = 0, parents = 4
Lot_id 22370: delivery_by_lot size = 0, parents = 1
Lot_id 25072: delivery_by_lot size = 6827, parents = 2
Lot_id 25134: delivery_by_lot size = 3, parents = 2
Lot_id 25135: delivery_by_lot size = 1, parents = 2
```
- Previous fix adds all child deliveries, even if some already exist, but this new patch adds only the missing ones
UPG - 3869661
OPW - 5900313
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#248826Imported PEPPOL BIS 4a customer invoices now use an additional fallback location to find supplier partner details. This helps ensure the correct partner is set automatically on invoices created from older e-invoice formats, reducing manual correction and import errors.
Original PR description
Currently, invoices created by uploading an e-invoice xml may not have the partner correctly filled in. Steps to reproduce: - Upload a customer invoice XML in format PEPPOL BIS 4a Issue: Partner is not set on the newly created record. On the chatter can be observed the message "Could not retrieve partner with details: Name: None, Vat: None, Phone: None, Email: None" Analysis: After https://github.com/odoo/odoo/commit/b4da4a77da3e0dc18707b935786b1924ca473796 we look for partner information under AccountingSupplierParty/Contact However older format may still be used to encode partner info under AccountingSupplierParty/Party opw-5970610
Down payment invoices now avoid creating untaxed lines when sales include products with fixed taxes. This prevents Peppol submission errors and helps ensure invoices remain compliant for electronic invoicing.
Original PR description
When making a downpayment for an order containing product using fixed taxes, the downpayment invoice would contain line without tax associated This is an issue when sending these invoices to Peppol. Steps to reproduce: ------------------- * Create a fixed tax of 5€ * Set this tax on any product along another tax * Create a sale order for this product * Make a downpayment of 10% * The invoice created has a line without any tax set > Observation: When sending to Peppol we get an error Why the fix: ------------ We remove the downpayment part that concerns fixed tax to avoid having lines without tax set. opw-5853070 Forward-Port-Of: odoo/odoo#252039
Users can now create new accounting journals even when a previous journal's default account has been archived. The change prevents duplicate account code errors by making the journal setup logic account for archived accounts, reducing manual workarounds for finance teams.
Original PR description
Backport of https://github.com/odoo/odoo/pull/249869 Description This PR addresses a critical validation issue in the accounting module where the system blocks the creation of new journals if a…
Backport of https://github.com/odoo/odoo/pull/249869 Description This PR addresses a critical validation issue in the accounting module where the system blocks the creation of new journals if a default account linked to an existing journal has been archived. Current Behavior Currently, when a user creates a new journal (e.g., a "Bank" type journal), the system automatically generates or assigns a default account. If the user subsequently archives that default account, any future attempt to create a new journal of the same type results in a Validation Error: "Account codes must be unique. You can't create accounts with these duplicate codes: [XXXXXX]" This happens because the system's uniqueness check for account codes includes archived accounts, but the automated journal setup logic fails to account for this state, effectively locking the user out from creating new journals until the archived account is manually renamed or unarchived. Desired Behavior After this PR is merged, users should be able to create new journals seamlessly, even if previous journals have archived default accounts. video https://drive.google.com/file/d/1VzAskdTwF7lNc1y8PIpvN0T2zzKTMtdJ/view 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#251025
Invoices that include fixed deposit-style taxes on returned items now generate Peppol-compliant electronic invoice data. This prevents validation failures when businesses process refunds or returns for consignment or empty-container deposits.
Original PR description
**PROBLEM** Here is the client use case: The client uses fixed tax to do 'vidange/consignage'. When selling a product with a 'consigne/vidange', they add a fixed tax which amount correspond to the…
**PROBLEM** Here is the client use case: The client uses fixed tax to do 'vidange/consignage'. When selling a product with a 'consigne/vidange', they add a fixed tax which amount correspond to the 'consigne/vidange'. When returning the 'consigne', you would create an invoice line, with a product with a price of 0, negative quantity,a 0% tax and the fixed tax for the 'consigne'. When an invoice contains such lines, it fails peppol validations. **STEP TO REPRODUCE** 1. Create a fixed tax used for 'vidange/consigne'. 2. Create an invoice, with a line with unit price of 0, negative quantity, a 0% tax and the fixed tax for the 'consigne'. 3. Send the invoice using peppol, use a validator to validate the xml and notice you get the following errors: [BR-E-01] [BR-E-08]. **CAUSE** Fixed tax (like the one used for vidange) are aggregated in new invoice lines by the function `_ubl_turn_emptying_taxes_as_new_base_lines()`. Let say we have the following invoice: line 1: qty=2, unit_price=3, taxes: 21% & vidange(fixed tax of 1). line 2: qty=-1, unit_price=0, taxes: 0% & vidange. After calling `_ubl_turn_emptying_taxes_as_new_base_lines()`, we got: line 1: qty=2, unit_price=3, taxes: 21%. line 2: qty=-1, unit_price=0, taxes: 0%. line 3: qty=1, unit_price=1(amount of the fixed tax), taxes:None. When generating the VAT breakdown, we have 2 line will end up being tax exempted (line 2 and 3). Because the `tax_exemption_reason` differs, they will not be merged in the same entry in the breakdown, which break the constraint of peppol saying we can only have one VAT breakdown with code 'Exempt from tax'. Line 2 reason comes from: https://github.com/odoo-dev/odoo/blob/de22093ee225df499b2de80e1f07dd281ac686bc/addons/account_edi_ubl_cii/models/account_edi_common.py#L271-L274 opw-5912986 Forward-Port-Of: odoo/odoo#250413
Field Service task imports now preserve the recurrence settings provided in the spreadsheet instead of replacing them with default values. This ensures imported recurring tasks are created with the intended schedule, reducing manual corrections after import.
Original PR description
### Steps to reproduce: - Create a xlsx sheet with some fsm_tasks values with recurrence values - Import the sheet to Field Service > Tasks - Navigate to the created tasks - Notice the recurrence values is the default ones not the ones in the imported sheet ### Cause: If we are importing records without recurrence_id value we will set the recurrence fields' values to the default values while we might already have values for those fields ### Fix: Check if we have values for recurrence fields we don't set the defaults and let the create method create the project.task.recurrence record and set the recurrence_id opw-5925546 Forward-Port-Of: odoo/odoo#249104
Invoices for Hungarian business partners can now use Hungary's domestic tax number format when creating electronic invoice data. This prevents valid Hungarian invoices from being blocked because their VAT number does not start with a country code.
Original PR description
Problem --------- When building the UBL, invoices with Hungarian partners get hit with the following constains: "The VAT of the [role] should be prefixed by the country code". However, Hungary allows for VAT numbers that do no start with the country code. Every Hungarian business is assigned a Tax Number (Adószám) that follows a fixed 11-digit format: NNNNNNNN-Y-CC. Solution --------- Build the VAT number from the Domestic Tax Number if it is not the case. no-task --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253663
Odoo now prevents users from deleting tax groups that are already used, reducing the risk of broken accounting records or reporting inconsistencies. Related point of sale tests were adjusted to deactivate taxes instead of deleting them, and tax usage checks were optimized for better performance.
Original PR description
Before this PR: - Group of taxes can be deleted by a user, even if they are used. After this PR: - If a user tries to delete a group of taxes in use, a validation error is raised. - Fixed a test case in POS and deactivated the tax instead of deleting the tax. Related PR: https://github.com/odoo/enterprise/pull/105174 task-5472834 Forward-Port-Of: odoo/odoo#245243
Users with read-only Accounting access can now import vendor bill XML files without encountering an error. This improves reliability for teams that separate invoice intake from accounting edits.
Original PR description
[FIX] account_edi_ubl_cii: restricted access user cannot import bill To reproduce: - create a user that has readonly access in Accounting - try to import a XML in vendor bills -> should traceback This commit modifies the `res_field` assignation by setting both `res_model` and `res_id` at the same time Forward-Port-Of: odoo/odoo#254698
This update resolves a bug where subscriptions were incorrectly marked as ‘In Progress’ after a credit note payment was processed. The fix prevents the reopening of churned subscriptions when a credit note payment (specifically refunds) is made, ensuring subscription status accurately reflects the customer’s account. This improves data accuracy and prevents potential disruptions to subscription management.
Original PR description
Steps to reproduce: ------------------------------ 1. Install Subscription module 2. Create a new subscription and confirm it 3. Create an invoice from the subscription. * Register a payment and…
Steps to reproduce: ------------------------------ 1. Install Subscription module 2. Create a new subscription and confirm it 3. Create an invoice from the subscription. * Register a payment and ensure the invoice is in the Paid state. 4. Go back to the subscription and close it with any reason 5. Open the related invoice. * Create and Confirm Credit Note. * Register a payment for the credit note. 6. Go back to subscription Observation: ------------------------------ The subscription is automatically set back to `In Progress` even though it was previously churned. Issue: ------------------------------ The method `_reopen_paid_churned_subscription` reopens churned subscriptions when an invoice is set to `in_payment` or `paid`. There was no check to exclude refund moves (`move_type = 'out_refund'`), causing the subscription to be reopened when a credit note is paid. Solution: ------------------------------ Add a condition to exclude refund invoices from the reopening logic opw-5947999 Forward-Port-Of: odoo/enterprise#108487
This update resolves a problem where the system incorrectly flagged invoices from intra-EU customers, leading to potential compliance errors with EU regulations. The fix ensures the 'Only intra-EU customers' check accurately identifies invoices for EC Sales List reporting, improving data accuracy and reducing the risk of non-compliance.
Original PR description
The EC Sales List return check "Only intra-EU customers" is reviewed when an invoice that match the condition for the warning same_country is present. To Reproduce: - Create a company in Belgium - Create a customer in Belgium with "Intra-Community" as a Fiscal Position - Create an invoice with this customer (in the previous month of the current month, for example February if the current date is in March - Open the Tax Returns - Open the EC Sales List Return - The Only intra-EU customers check is reviewed when it should show an anomaly. Forward-Port-Of: odoo/enterprise#107137
This update resolves an issue preventing new employee creation when generating BVG-LLP reports with duplicate monthly data. The fix addresses a technical problem within Odoo's record processing that caused a 'singleton' error. This ensures employees can be created correctly when multiple reports with the same month are present.
Original PR description
Steps to reproduce: ---------------------------------- 1. Install `l10n_ch_hr_payroll_elm_transmission` module 2. Switch to Swiss company 3. Navigate to Payroll > Transmission > BVG-LLP Basis…
Steps to reproduce:
----------------------------------
1. Install `l10n_ch_hr_payroll_elm_transmission` module
2. Switch to Swiss company
3. Navigate to Payroll > Transmission > BVG-LLP Basis Declaration
4. Create two Reports with same Year and Month
5. Now try to create new Employee from the employee app
Observation:
----------------------------------
Tracaback Occurs:
```
File '/home/odoo/src/enterprise/19.0/l10n_ch_hr_payroll/models/l10n_ch_employee_monthly_values.py', line 319, in _compute_bvg_lpp_annual_basis
existing_declaration = max(existing_declaration, key=lambda r: r.month) if existing_declaration else False
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File '/home/odoo/src/odoo/19.0/odoo/orm/models.py', line 5934, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: l10n.ch.lpp.basis.report(1, 2)
```
Issue:
----------------------------------
In the following code:
https://github.com/odoo/enterprise/blob/44a26539093f9313d9cd5f823c11866e3c98ec97/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_employee_monthly_values.py#L319-L320
Python's max() function doesn't just call the key function once per item. When there are ties (equal key values), it may need to compare the original objects, and during this process, Odoo's recordset operations combine records, causing the lambda receives `r` as a combined recordset. To access `.month` on a multi-record recordset it gives singleton error.
Solution:
----------------------------------
Creates tuples of (month, recordset) pairs and uses max() to compare month integers directly, avoiding the singleton error.
opw-5391742
Forward-Port-Of: odoo/enterprise#102335This update resolves an issue where Odoo generated invalid UBL/QR invoices for foreign customers when a Peruvian company was invoicing a customer with a different country's identification type. The change ensures the correct 'schemeID' value ('0') is used, preventing errors with SUNAT and ensuring proper invoice generation in multi-country scenarios.
Original PR description
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an…
In multi-country databases, a Peruvian company can invoice a foreign customer (e.g., a Colombian company) whose identification type is defined by another localization. Those records typically have an empty l10n_pe_vat_code, since there are no cross-country dependencies between LATAM identification types. In that case, the generated UBL leaves the receiver identity type empty and SUNAT returns an error like: ``` 2015/2015 - El XML no contiene el tag o no existe informacion del tipo de documento de identidad del receptor... (missing schemeID value). ``` Odoo already defines schemeID = 0 for some foreign identification types in l10n_pe data, but it cannot cover identification types coming from other countries’ localizations (e.g. Colombia): https://github.com/odoo/odoo/blob/18.0/addons/l10n_pe/data/l10n_latam_identification_type_data.xml#L4 This change ensures that, when the partner is not from Peru and the PE VAT code is missing, we fallback the receiver identification type to "0" in: - PartyIdentification/ID/@schemeID - AccountingCustomerParty/AdditionalAccountID - the QR payload identification type field This prevents generating invalid UBL/QR content for foreign customers in multi-country setups. Forward-Port-Of: odoo/enterprise#105115
This update corrects an issue where incorrect folio numbering occurred when a Chilean Accounting (l10n_cl_edi) configuration wasn't set up. The fix ensures folios are correctly generated, preventing errors and maintaining accurate accounting sequences. This improves the reliability of financial data for Chilean users.
Original PR description
`l10n_cl_edi` overrides `account.move._get_last_sequence()` to ensure the folio belongs to an available in-use CAF. When no CAF exists at all, `l10n_latam.document.type._get_start_number()` returns 0 and the fallback builds a previous sequence using start_nb - 1. Formatting -1 as `:06d` yields “-00001”, which then propagates to “FAC -00002”, “-00003” and corrupts the sequence chain. In addition, returning an invalid “last sequence” may force `sequence.mixin` to search for a free number under the UNIQUE constraint by retrying increments inside a savepoint and rolling back on UniqueViolation, which is costly when many values are already taken see [ _locked_increment()](https://github.com/odoo/odoo/blob/18.0/addons/account/models/sequence_mixin.py#L352). Now we only reset to the CAF start when an in-use CAF actually exists (start_nb > 0). opw-5918758 Forward-Port-Of: odoo/enterprise#108909
This update resolves an issue where generating VAT reports (FAIA) for invoices in different currencies caused a rendering error. The fix ensures the necessary currency information is included in the report, allowing accurate VAT calculations for Luxembourg companies. This improves the reliability of financial reporting.
Original PR description
Steps to reproduce 1/ setup a LU company. The default company currency will be EUR. 2/ create a vendor bill in another currecy (e.g. USD) 3/ take note of the bill date and accounting date (ideally set them in the past, like 1 month) 4/ generate the FAIA report for the period containing the created bill => error while rendering the qweb template The core of the error is when rendering the l10n_lu saft template. Sales invoices and purchase invoices reuse the standard `account_saft.tax_information` report, which expects to find `currency_code` in the object's fields. This commit explicitly re-adds it when creating the document's tax summary. opw-5216057 Forward-Port-Of: odoo/enterprise#110660 Forward-Port-Of: odoo/enterprise#106902