Friday, March 20, 2026
39 changes · saas-19.1
New functionality added to Odoo
This update reflects recent changes in Belgian tax regulations regarding deductible expenses. The update modifies key fiscal categories (accounts 616580, 616541, 623610) to align with the latest government rules, ensuring accurate accounting for our Belgian clients.
Original PR description
Belgian Government changed some rules regarding the fiscal deductibility of some expenses, so we need to update that data accordingly for accounts 616580, 616541, 623610 Task-5973880 Forward-Port-Of: odoo/enterprise#110075
This update adds a new tax specifically for incapacity to work income in Spain, aligning with AEAT requirements. It ensures accurate reporting of withholdings on this income type, preventing errors on Form 190 and improving tax compliance for Spanish businesses.
Original PR description
### Description of the feature this PR addresses: **Specific tax on withholdings for incapacity to work created to correctly reflect the amounts derived in Form 190 of the AEAT.** A new tax called…
### Description of the feature this PR addresses: **Specific tax on withholdings for incapacity to work created to correctly reflect the amounts derived in Form 190 of the AEAT.** A new tax called "**100% WHI monies**" has been created with the aim of correctly reflecting the income derived from incapacity for work in the AEAT's Model 190. ### Current behavior before PR: Currently, Odoo does not allow automatic differentiation between monetary payments derived from work incapacity and those not derived from it. This creates a problem when generating Model 190, as the Spanish Tax Agency (AEAT) requires both types of payments to be reported separately (according to the codes and subcodes established in the model). **In practice, this separation is necessary because:** - Income derived from incapacity for work (e.g., sick leave) is considered employment income with differentiated tax treatment. - Withholdings made on these amounts must be declared in specific sections of Form 190. - If they are not separated correctly, the totals on the form may be incorrect or incomplete, affecting the accuracy of the tax information submitted. ### Desired behavior after PR is merged: A new tax has been added to represent “100% Withholding income tax (workers)”, allowing Odoo to: - Correctly identify and calculate the related amounts. - Report them separately in the AEAT Model 190. - A new tax group has also been created to distinguish these withholdings from regular ones. ### Benefits: - It allows you to correctly generate Form 190, separating income derived from and not derived from work disability. - It facilitates the accounting and tax traceability of this type of income. - It ensures consistency with the information structure required by the Spanish Tax Agency (AEAT), avoiding errors in the annual filing. - It improves the flexibility of the Odoo tax system, adapting it to actual tax needs. ### Technical summary: - A **new specific tax** has been created for withholdings associated with incapacity for work benefits. - This tax **allows the amounts corresponding to these benefits to be identified, accounted for, and reported independently.** - In addition, a **new tax group "Whitholdings IRPF Workers" has been added that groups these withholdings together**, allowing them to be clearly distinguished from other withholdings on earned income. The related issue: https://github.com/OCA/l10n-spain/issues/4416 ### Follow-up suggestion: adjust Odoo’s base tax “15% WHI monies” **Proposal:** Change the base tax “15% WHI monies” to 100% and move it to the new “Whitholdings IRPF Workers” tax group. **Why:** The current 15% rate is not aligned with how AEAT Model 190 requires amounts to be computed: the base should reflect 100% of the earnings derived from temporary incapacity, with the withholding rate applied on top of that base. Keeping 15% leads to misclassification and wrong totals in the "_percepciones_" and "_retenciones_" sections. These are variable withholdings, not fixed taxes — each worker’s rate can change monthly depending on their income and number of days worked. Therefore, having a fixed 15% rate is conceptually incorrect and causes misclassified amounts and inaccurate totals, forcing users to adjust values manually after payroll. Ideally, this tax should not have any fixed percentage defined. Since Odoo currently requires a rate, setting the base to 100% is a pragmatic workaround that ensures more accurate and flexible withholding calculations. **Outcome:** - Correct calculation and reporting of **_percepciones derivadas de incapacidad laboral_**. - Clean separation from other withholdings via the new tax group. - Consistency between accounting, payroll, and the 190 export. Would you accept this change? @moduon @rafaelbn @EmilioPascual @chklop @jco-odoo MT-11667 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#245553 Forward-Port-Of: odoo/odoo#232515
Enhancements to existing features
This update enhances the security and reliability of exporting large spreadsheet datasets from Odoo. It adds logging for common export scenarios (downloading, copying, printing) and restricts access to frozen or XLSX spreadsheets to authorized users, preventing unauthorized data access. This improves data integrity and security.
Original PR description
Forward-Port-Of: odoo/enterprise#108959 Forward-Port-Of: odoo/enterprise#85888
Resolved issues and error corrections
This update resolves an error that occurred when creating payments for invoices using the Bacs Direct Debit method. The fix ensures that the system correctly handles scenarios where a company's bank account information is missing, preventing a validation error and ensuring payment processing works as expected.
Original PR description
Currently, an error occurs when user creates a payment for an invoice. **Steps to Reproduce:** - Install `l10n_uk_bacs` with demo data. - Switch to the `UK company`. - Go to `Journals`, select the…
This update ensures that product information in the website includes the product SKU (or default code), improving clarity and accuracy for users. It also resolves an issue where imported product variants weren't visible, allowing users to directly manage and see their created variants.
Original PR description
An important change for the products to include the SKU (or default_code in Odoo) to the products. Also now set the variant setting on so that the user can see the variants created directly without having this confusing in-between where we import variants but they cannot see them.
This pull request enhances the handling of BIS3 invoices within the account_edi_ubl_cii module. It removes outdated functions related to UBL creation, streamlining the process and ensuring compatibility with BIS3 standards. This change improves the accuracy and efficiency of invoice generation for BIS3 transactions.
Original PR description
Deprecate: _ubl_add_base_line_ubl_values_item _ubl_get_line_item_node _ubl_add_base_line_ubl_values_price _ubl_add_values_payable_amount_tax_withholding _ubl_add_values_payable_rounding_amount _ubl_add_values_allowance_charge_early_payment _ubl_add_values_tax_currency_code_company_currency_if_foreign_currency _ubl_add_values_tax_currency_code_company_currency _ubl_add_values_tax_currency_code_empty _ubl_add_values_tax_currency_code --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253688 Forward-Port-Of: odoo/odoo#249823
This update enhances the spreadsheet functionality by adding detailed logging when exporting large datasets, including downloads, clipboard copies, and printing. It also strengthens security by restricting the ability to download frozen spreadsheets to authorized users, preventing unauthorized data access.
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#251031 Forward-Port-Of: odoo/odoo#210592
Currently, an error occurs when user creates a payment for an invoice. **Steps to Reproduce:** - Install `l10n_uk_bacs` with demo data. - Switch to the `UK company`. - Go to `Journals`, select the `Bank Journal`, and remove the `Bank Account Number`. - Go to `Invoices` and create an invoice by adding an `invoice line` with price greater than zero. - `Confirm` the invoice. - Click `Pay`, select `Bacs Direct Debit` as the payment method, and click `Create Payment`. `ValueError: Expected singleton: res.partner.bank()` This error occurs when creating a payment for an invoice using the Bacs Direct Debit payment method. The constraint check bacs bank account trigger [1], but since the journal has no bank account number, it raises an error here [2]. Similar error also occurs when validating a batch payment [3]. This commit ensures that if the journal has no bank account, or if the bank account is invalid, the system raises the same validation error. In batch mode, it raises a UserError when the account is missing. [1]: https://github.com/odoo/enterprise/blob/8405155aa94b4f26efb202cbf815e874375a7f49/l10n_uk_bacs/models/account_payment.py#L52-L58 [2]: https://github.com/odoo/enterprise/blob/8405155aa94b4f26efb202cbf815e874375a7f49/l10n_uk_bacs/models/res_partner_bank.py#L18-L19 [3]: https://github.com/odoo/enterprise/blob/8405155aa94b4f26efb202cbf815e874375a7f49/l10n_uk_bacs/models/account_batch_payment.py#L74 sentry-7259107152
This update resolves a bug where subscriptions would incorrectly revert to an 'In Progress' state after a credit note payment was processed. The fix prevents the reopening of subscriptions when a credit note payment (specifically refunds) is made, ensuring subscription status accurately reflects the payment cycle. This improves subscription management and prevents disruptions.
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 fixes an issue where multiple email addresses on a contact were being overwritten when creating a helpdesk ticket. The change ensures that all email addresses associated with a contact are correctly captured, improving the reliability of ticket creation. This resolves a potential data loss scenario.
Original PR description
Prerequisites: ------------------------------ 1. Set up incoming mail server with Create a New Record set to Helpdesk Ticket 2. From Settings, create one Alias Domain Steps to reproduce:…
Prerequisites: ------------------------------ 1. Set up incoming mail server with Create a New Record set to Helpdesk Ticket 2. From Settings, create one Alias Domain Steps to reproduce: ------------------------------ 1. Install Helpdesk module 2. Open Helpdesk Team > Settings 3. Inside Channels, Set the mail used for the incoming server and the alias created 4. Set Accept Emails From to Everyone 5. Create a new contact with multiple emails (eg: `a@b.com`, `c@d.com`) 6. From Fiest mail (eg: `a@b.com`), Send one mail to mail set in the helpdesk team alias mail. 7. Open Incoming mail sever > Click on Fetch Now 8. Open Created Contact Observation: ------------------------------ The contact's email field is overwritten. The second email address (e.g. `c@d.com`) is lost Issue: ------------------------------ After `create`, since `partner_email` was stored with a value that differs from `partner_id.email`, the inverse method `_inverse_partner_email` kicks in. This is where `_get_partner_email_update()` is called. In `_get_partner_email_update()` `tools.email_normalize()` only handles a single email. When the partner has multiple email, the normalization keeps both, while the ticket email normalizes to just have one mail. The strict `!=` comparison fails, triggering the unwanted update. https://github.com/odoo/enterprise/blob/7c23efafe368787c858db31cec075f642ae6715b/helpdesk/models/helpdesk_ticket.py#L363-L369 Solution: ------------------------------ Instead of comparing the full normalized strings, we should check whether the ticket's normalized email is contained within the set of the partner's normalized emails Note for reviewer ----------------------------- After discussion with the PO (LNA), his opinion is that having multiple email addresses in a single field is not a good practice. This use case is only semi-supported in Odoo, it may work in some cases, but it is not reliable. The recommended approach is to create separate contacts for each email address. That said, we should also avoid automatically clearing or altering the existing value in the field. Based on this, I have implemented a minimal fix that prevents altering the existing value in the field. I am leaving it up to the review to decide whether this fix is worth keeping from a technical standpoint. opw-5478067 Forward-Port-Of: odoo/enterprise#107808
This update fixes an issue where subscription products weren't displaying prices with tax, even when the website setting was enabled to show tax-inclusive prices. The fix ensures that the correct tax rates are applied based on the customer's company, resolving a discrepancy in how product company IDs were being evaluated. This ensures accurate pricing for all subscription customers.
Original PR description
subscriptions Despite enabling the website setting to display tax-inclusive prices, subscription products show prices without tax when a recurring pricelist is configured. In `_get_sales_prices`, the product’s company ID is compared to the website’s company, but products visible to all have a false company ID, and products assigned to a parent company retain the parent’s company ID. As a result, when the product’s company ID does not match the website’s company ID, no taxes are applied.Instead, _filter_taxes_by_company should be used to determine whether the company can access the product’s tax_id. opw-5222411 Forward-Port-Of: odoo/enterprise#102102 Forward-Port-Of: odoo/enterprise#100662
This update resolves a problem where incorrect invoice folio numbers (starting with negative signs) were being generated when no Chilean Fiscal Authorization File (CAF) was configured. The fix ensures that folios are correctly generated based on available CAF numbers, preventing sequence corruption and costly database retries. This improves invoice accuracy and stability 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 financial reports (FAIA) for Luxembourg companies using multi-currency vendor bills resulted in errors. The fix ensures the necessary currency information is included in the report template, allowing for accurate reporting of sales and purchase taxes. This improves the reliability of financial data for Luxembourg businesses.
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
This update resolves an issue where payrun calculations were failing when an employee's contract started mid-period. The fix ensures accurate integration factor calculations for new hires with staggered contract start dates, preventing incomplete payrun generation. This improves payroll accuracy for new employees.
Original PR description
An error is thrown when an employee's contract starts mid-period. ```py Invalid Operation Wrong python code defined for: - Employee: Cesar Osbaldo Cruz Solorzano - Version: False - Payslip: Payslip -…
An error is thrown when an employee's contract starts mid-period.
```py
Invalid Operation
Wrong python code defined for:
- Employee: Cesar Osbaldo Cruz Solorzano
- Version: False
- Payslip: Payslip - Cesar Osbaldo Cruz Solorzano - 01/16/2026 - 01/31/2026
- Salary rule: Integrated Daily Wage (Base) (INT_DAY_WAGE_BASE)
- Error: AttributeError("'bool' object has no attribute 'year'") while evaluating
'\nresult = round(payslip.l10n_mx_integration_factor * payslip.l10n_mx_daily_salary, 4)\n
```
Steps to reproduce:
1. Install `l10n_mx_hr_payroll` modules
2. Switch to ESCUELA KEMPER URGATE company
3. Go to Employees and open Cesar Osbaldo Cruz Solorzano
4. Go to Payroll tab, change the start date of contract to 01/10/2026 and save
5. Go to Payroll > Payslips > Payslips and create a new pay run
6. Select Salary Structure 'Mexico: Regular Pay', Pay Schedule 'Monthly' and Period '01/01/2026 -> 01/31/2026'
7. Click on Continue, select Cesar and click on Select
8. An error is thrown
Problem:
In `_compute_integration_factor` method, `_get_first_contract_date` is called with context `before_date`, it returns `False` as the contract starts after the payslip period. This causes an error when trying to access the `year` field of `start_date`.
Solution:
Add a fallback to call `_get_first_contract_date` without context in case the first call returns `False`.
target: saas-18.4
task-6034836
Forward-Port-Of: odoo/enterprise#110568This update resolves an issue where the bulk payments feature would crash if a bank journal wasn't properly connected. A new user message has been added to alert users when a journal isn't linked to a bank, preventing the error and improving the user experience.
Original PR description
This commit: https://github.com/odoo/enterprise/commit/c9cc89f58f7d98396afac3bdacfeff9b00a02a21 introduce the initiate bulk payments feature. When selecting a batch you can also check the status of this batch. But for the moment, if you select a batch that is not connected to a bank, the action will traceback with a redirect. This commit will add a user error to warn the user than the journal needs to be connected to a bank. task-6009083 Forward-Port-Of: odoo/enterprise#111031 Forward-Port-Of: odoo/enterprise#109956
This update corrects a potential issue where calculations for employee payslips were unintentionally impacting a large number of records. The change now limits the calculation to active payslips, ensuring accurate and reliable payroll processing. This improves data integrity and reduces the risk of errors.
Original PR description
Before this commit, `_compute_basic_net` was not limited to specific payslips, potentially affecting thousands of records and even more of `hr.payslip.line` records. This commit restricts the compute to ongoing payslips. task-6022499 Forward-Port-Of: odoo/enterprise#110069
This update resolves an issue preventing new employee creation when generating BVG-LLP reports. The fix addresses a technical problem with how Odoo compares report data, ensuring the system correctly handles multiple reports with the same month.
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#111084
Forward-Port-Of: odoo/enterprise#102335This update fixes an issue in the Spanish (ES) balance sheet reports where retained earnings were incorrectly excluded. Now, all relevant equity adjustments are accurately reflected, ensuring consistent and reliable equity totals. This improves the accuracy of financial reporting for Spanish businesses using Odoo Enterprise.
Original PR description
Description of the issue this commit addresses: The ES balance sheet “prior periods” line only matched code 12, so retained/unaffected earnings posted on other codes were skipped, which could understate or skew equity totals. --- Desired behavior after this commit is merged: The line now includes both accounts with code 12% and accounts of type equity_unaffected, so carried-forward results are always included and equity totals stay consistent. --- task-6047627 Forward-Port-Of: odoo/enterprise#111249
This update resolves a validation error occurring when invoices for 'Final Consumers' in Argentina lack a VAT/CUIT number. The system now correctly sends a 'null' value for the DocNro field, aligning with ARCA's requirements and preventing invoice rejection. This ensures compliance and smooth processing of these transactions.
Original PR description
**Description of the issue/feature this PR addresses:** This PR fixes a validation error (Code 10015) returned by ARCA (formerly AFIP) when attempting to validate invoices for "Final Consumers"…
**Description of the issue/feature this PR addresses:** This PR fixes a validation error (Code 10015) returned by ARCA (formerly AFIP) when attempting to validate invoices for "Final Consumers" (Consumidor Final) who do not have a VAT/CUIT number assigned. The system currently defaults the DocNro field to 0, which is rejected by the fiscal authority's web service. **Current behavior before PR:** When a contact is marked as "Final Consumer" but lacks a specific ID number (VAT/CUIT), the integration sends DocNro: 0 to ARCA. This triggers Error 10015, as "0" is not considered a valid identification number for this responsibility type, leading to a blocked invoice. **Desired behavior after PR is merged:** For contacts meeting these conditions (Final Consumer without a defined ID), the system will now automatically categorize the transaction as "sigd" (System Identified/Global Data) instead of a standard Final Consumer. By doing this, the DocNro is sent as None (or null), which is the legally accepted format by ARCA for these specific cases, successfully bypassing the validation error. Forward-Port-Of: odoo/enterprise#106881
This update resolves an issue where downpayment invoices generated with fixed taxes incorrectly lacked tax line items, causing errors when sending invoices to Peppol. The fix removes the problematic downpayment processing for fixed taxes to ensure accurate invoice creation and compliance with Peppol standards.
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
This update fixes an issue where reasons provided by Public Administrators when refusing invoices weren't displayed in Odoo. Now, the reason message (EsitoCommittente/Descrizione) is shown on the invoice's header, ensuring accurate record-keeping for invoice refusal events as required by Italian regulations. This improves compliance with the FatturaPA standard.
Original PR description
When a Public Administrator business refuses an invoice, they also give a reason message (EsitoCommittente/Descrizione), which comes through the IAP to Odoo as an XML tag aside the Outcome code (EsitoCommittente/Esito). Before this PR, the message was ignored, now we show it in the invoice's header. ref: https://www.fatturapa.gov.it/export/documenti/messaggi/v1.1/MessaggiTypes_v1.1.xsd <img width="823" height="232" alt="image" src="https://github.com/user-attachments/assets/8f222f6b-1615-4dd2-a5dd-25e0991ea037" /> <img width="942" height="206" alt="image" src="https://github.com/user-attachments/assets/cdf109ff-40d0-4c50-bdc7-51fb4ea15c98" /> Ticket [link](https://www.odoo.com/odoo/project.task/6041276) opw-6041276 Forward-Port-Of: odoo/odoo#254481
This update fixes an issue where payslips were incorrectly saving archived employee versions. Now, when a payslip is generated, it will only use unarchived versions, ensuring accurate data and preventing confusion when updating employee information. This improves data integrity and simplifies payroll processing.
Original PR description
In this commit, the versions on payslips are restricted to only unarchived ones. This ensures that when changing dates/employee, the version selected is never archived. Task-6022151 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#253348
This update resolves an issue preventing users from creating new journals when a previously archived default account was linked to a journal. Previously, the system blocked new journal creation due to a uniqueness check that included archived accounts. Now, users can create new journals seamlessly, even with archived accounts, improving usability and preventing workflow disruptions.
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
This update ensures that users are always notified when a vendor bill is sent to the 'Purchases' journal, regardless of whether the bill was automatically digitized. Previously, the digitization process would prevent email notifications. This change improves communication and ensures timely receipt of important financial information.
Original PR description
When vendor bills digitization is deactivated, subscribers to the "Purchases" journal are not notified when a vendor bill is sent to the email alias set on the "Purchases" journal Steps to reproduce:…
When vendor bills digitization is deactivated, subscribers to the "Purchases" journal are not notified when a vendor bill is sent to the email alias set on the "Purchases" journal Steps to reproduce: 1. Install Accounting 2. Go to Settings > Accounting > Digitization and set Vendor Bills to "Do not digitize" 3. Go to Settings > Technical > Email > Alias Domains and create a new alias domain (e.g. "odoo.com") 4. Go to Settings > Technical > Email > Incoming Mail Servers and create a new incoming mail server (e.g. "megu@odoo.com", you may need to setup POP access on your email address and create an app password, see https://support.google.com/mail/answer/7104828) 5. Go to Accounting > Configuration > Journals and open journal "Purchases" 6. Go to Advanced Settings tab and set the Email Alias and the Send Copy To fields (e.g. "megu@odoo.com" for both) 7. Send a mail with an attachment to the email alias set on the "Purchases" journal 8. Go to the previously created incoming mail server and click on Fetch Now 9. Go to Settings > Email > Technical > Emails 10. No email has been sent to the subscriber of the "Purchases" journal Issue: `_extend_with_attachments` returns None if the OCR import failed https://github.com/odoo/odoo/blob/b44295bb6ce621ff87cbc96860492650d90d0ad7/addons/account/models/account_document_import_mixin.py#L340-L349 which prevents the call to method `_notify_invoice_subscribers` Solution: Send an email regardless of the result of the OCR import opw-5914096 Forward-Port-Of: odoo/odoo#252442
This update resolves issues where invoices with global discounts or down payments were incorrectly sending negative values to the Sinvoice system, causing errors. The fix now properly handles these scenarios and includes support for uploading note lines on invoices, ensuring accurate data transmission for Vietnamese VAT reporting.
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#254648 Forward-Port-Of: odoo/odoo#251913
This update fixes an issue where changing the lot number of a combo product in Point of Sale (POS) would reset the order total price. The fix ensures that the price remains consistent with the combo product's defined price, regardless of lot changes. This improves the accuracy of POS transactions.
Original PR description
Step to reproduce: - have a lot tracked product, product 1 (price = 10) - create a combo product with product 1, with price (100) - start a pos, add combo product in order, - notice total price is 100 - change lot number of product 1, - notice order price reset to 10. Cause: - When the lot number is changed, `set_quantity_by_lot` is triggered. - This calls `set_quantity`, which resets the price and loses the combo pricing. Fix: - use `keep_price` = true parameter when calling `set_quantity` if orderline has combo_parent_id opw-5495409 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#254278 Forward-Port-Of: odoo/odoo#246252
This update resolves a memory issue that occurred when exporting large financial data files (FECs) from our accounting system. By streaming the data instead of loading the entire file into memory, the export process is now more efficient and reliable, especially for large databases. This ensures smoother and faster data exports.
Original PR description
On large databases (millions of account moves), The FEC exported file can be huge. This resulted in memory error since at some point we have the entire file in memory. This commit aims to overcome this issue by streaming the content of the file to the user. task-5404142 Forward-Port-Of: odoo/odoo#248027 Forward-Port-Of: odoo/odoo#240981
This update adds detailed error information to screenshot failures, helping developers quickly diagnose issues with the website's visual components. The changes capture more context from browser errors, specifically related to timeouts and service worker shutdowns, to pinpoint the root cause of these failures. This improves debugging and reduces the time to resolve website visual problems.
Original PR description
Trying to investigate this common issue: https://runbot.odoo.com/runbot/build/104596176 script timeout exceeded -> internal error during screenshot + timeout error when trying to shut down service…
Trying to investigate this common issue:
https://runbot.odoo.com/runbot/build/104596176 script timeout exceeded -> internal error during screenshot + timeout error when trying to shut down service workers (but oddly `Page.stopLoading` worked so the browser might not be entirely hosed?)
https://runbot.odoo.com/runbot/build/104598123 and https://runbot.odoo.com/runbot/build/104599315 only parsed a timeout during service workers shutdown, but looking at the logs they actually have the same error, it's just that the in-band error is suppressed by the retry, but then the traceback finder goes and triggers on the TB it finds in the logs (but only the last link of the TB so the thing is cut off):
```
2026-03-19 03:48:11,239 26 INFO 104599315-saas-19-1-all odoo.addons.website.tests.test_snippets.TestSnippets.test_03_snippets_all_drag_and_drop: Asking for screenshot
2026-03-19 03:48:11,241 26 INFO 104599315-saas-19-1-all odoo.addons.website.tests.test_snippets.TestSnippets.test_03_snippets_all_drag_and_drop: Couldn't capture screenshot: Internal error
2026-03-19 03:48:21,249 26 _WARNING 104599315-saas-19-1-all odoo.tests.common: Error during browser shutdown
Traceback (most recent call last):
File "/data/build/odoo/odoo/tests/common.py", line 2566, in browser_js
self.fail(str(error))
File "/usr/lib/python3.12/unittest/case.py", line 715, in fail
raise self.failureException(msg)
AssertionError: Script timeout exceeded
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/build/odoo/odoo/tests/common.py", line 1664, in _websocket_request
return f.result(timeout=timeout * self.throttling_factor)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/concurrent/futures/_base.py", line 458, in result
raise TimeoutError()
TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/build/odoo/odoo/tests/common.py", line 1375, in _ws_winddown
self._websocket_request('Runtime.evaluate', params={'expression': """
File "/data/build/odoo/odoo/tests/common.py", line 1666, in _websocket_request
raise TimeoutError(f'{method}({params or ""})')
TimeoutError: Runtime.evaluate({'expression': "\n ('serviceWorker' in navigator) &&\n navigator.serviceWorker.getRegistrations().then(\n registrations => Promise.all(registrations.map(r => r.unregister()))\n )\n ", 'awaitPromise': True})
```This update resolves a problem where discounts weren't consistently applying correctly when switching between fiscal positions (which handle taxes) in the Point of Sale system. The fix ensures that discounts are recalculated accurately based on the current fiscal position, preventing incorrect line amounts. This improves the reliability of discount calculations for all users.
Original PR description
Steps to reproduce ------------------ 1. Make two fiscal positions, one applying taxes, and the other not. 2. Open pos, select the FP that applies taxes, and add a product 3. Now apply a global discount of 10% 4. Chagne to the FP that does not apply any taxes. Notice that the discount line amount is still computed based on the the taxes from the old FP. Also, another "unrelated" bug, when adding products, the global discount was not always updating. Please see the individual commits' messages for more details on each fix. opw-5443716 Forward-Port-Of: odoo/odoo#246387
This update resolves an issue where users with Manufacturing and Timesheet permissions couldn't complete Manufacturing Orders due to access restrictions on linked analytic lines. The change allows users to correctly link analytic lines to work orders, ensuring smooth order production without errors. This improves usability for all users.
Original PR description
Issue before this commit: ========================= Clicking Produce All on a Manufacturing Order as a user with Manufacturing and Timesheet rights raised an AccessError. During Manufacturing Order…
Issue before this commit: ========================= Clicking Produce All on a Manufacturing Order as a user with Manufacturing and Timesheet rights raised an AccessError. During Manufacturing Order completion, Odoo creates analytic lines for work center cost distribution and links them to the work order through the wc_analytic_account_line_ids Many2many field. With the stricter ORM security checks, linking records in a Many2many field requires read access to those records. Since analytic lines are created using sudo() but the relation update runs under the current user's permissions, the operation fails due to timesheet-related record rules. Steps to Reproduce: ========================= 1. Install mrp_account and hr_timesheet modules. 2. Create a Work Center with an analytic distribution. 3. Create a Product with a Bill of Materials (BoM) that includes a work order using the created Work Center. 4. Log in as a non-admin user with Manufacturing and Timesheet permissions. 5. Create and confirm a Manufacturing Order for that product. 6. Click Produce All. Cause of the Issue: ========================= Analytic lines are created with sudo(), but when linking them to the work order through the Many2many field wc_analytic_account_line_ids, the ORM checks whether the current user has read access to those records. Due to timesheet record rules restricting access to analytic lines, the linking operation raises an AccessError. With This Commit: ========================= This commit allows users to complete Manufacturing Orders without encountering access errors when analytic lines are linked to work orders, while preserving the existing analytic distribution and security logic. For Reference: [Security checks on Many2many](https://github.com/odoo/odoo/pull/217277/changes#diff-720a85988e5f3afc3b2596b9521964ef4a99e03e5b1ea8bea2e8ee476187526aR1467) Steps To Reporduce: [Video Link](https://drive.google.com/file/d/1HsZjpFSsnsYxZ4xwM8CBDeLhlcIHIP5t/view) opw-5971807 Forward-Port-Of: odoo/odoo#253496
This update fixes a problem in the POS Restaurant dashboard where pivot tables weren't displaying the full dataset (15 rows) or sorting 'Top' values correctly. The changes ensure all rows are used, pivots are sorted as expected, and column names accurately reflect the data, leading to more reliable reporting.
Original PR description
## Description of the issue/feature this PR addresses: Current behavior before PR: - In the POS Restaurant dashboard, most pivot tables have 15 available rows, but only the first 10 rows are used. - Pivots meant to display 'Top' values were not properly sorted. - Some column names did not correctly represent the values they contain. Desired behavior after PR is merged: - Pivot tables now use all 15 available rows. - Pivots are sorted when required by the relevant columns. - Column names now correctly represent the values they contain. Task: [6019270](https://www.odoo.com/odoo/project/2328/tasks/6019270) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253256
This update fixes an issue where invoice previews in the portal displayed text in the wrong direction (LTR) for Arabic-speaking users. The fix ensures the correct RTL layout is applied, improving the user experience for international customers. Additionally, the subtotal layout for Saudi invoices has been adjusted to prevent visual clipping of tax totals.
Original PR description
When opening invoice HTML preview in the portal, the layout was displayed in LTR even if the invoice partner language was RTL (e.g. Arabic). This happened when the portal user language was LTR. PDF…
When opening invoice HTML preview in the portal, the layout was displayed in LTR even if the invoice partner language was RTL (e.g. Arabic). This happened when the portal user language was LTR. PDF structure was correct, but HTML preview had wrong text flow and alignment. Root cause was that RTL asset processing depends on `env.lang`, not on `t-lang` in templates. Since the ORM context language remained the portal user’s language, CSS was compiled in LTR and hardcoded `direction: ltr;` rules from `report.scss` were overriding the `<html dir="rtl">`. To fix this, the portal controller now checks the partner language and, if it is RTL, updates the request context before rendering. This ensures `_render_qweb_html` runs with the correct `env.lang`, triggering proper RTL CSS conversion via rtlcss. Additionally, the subtotal section in the Saudi invoice report could have its values visually cut due to insufficient width allocated to the tax totals column. The column width has been slightly increased to ensure totals are properly displayed. task-5878719 Forward-Port-Of: odoo/odoo#248822
This update fixes an issue where sales order margins were incorrectly calculated due to a misunderstanding of the company context. The fix ensures margins are accurately determined based on the company associated with the specific sales order line, regardless of the user's default company setting. This improves the reliability of margin reporting.
Original PR description
Steps to reproduce: - Have 2 companies: - Company A with a property_cost_method 'average' - Company B with a property_cost_method 'standard' - Create a sales order in B - Set the default company of the user to A. - Under certain scenarios, when we confirm the sales order, there will be a `flush_all`. - When that's the case, margins are recomputed with `line.product_id.categ_id.property_cost_method` as `average` instead of `standard`. In other words, it will take the property_cost_method from the `user.company_id` (A), instead of the property_cost_method from the `line.company_id` (B). This fix ensures the `property_cost_method` considered is the one related to the company of the sale order line. A similar issue was fixed on https://github.com/odoo/odoo/pull/192890 OPW-5939464 Forward-Port-Of: odoo/odoo#254489 Forward-Port-Of: odoo/odoo#252161
This update prevents users from deleting tax groups that are currently in use within the system. Previously, deleting a tax group could lead to errors. Now, a validation error is displayed, ensuring data integrity and preventing potential issues with financial reporting and transactions. This change improves the reliability of our accounting processes.
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#254730 Forward-Port-Of: odoo/odoo#245243
This update fixes an issue where overpayments made via bank payment in Point of Sale didn't create the necessary accounting records. Now, when a customer pays more than the order amount using a bank payment, a corresponding accounting line is created, ensuring accurate financial reporting. This prevents the system from incorrectly showing an outstanding balance.
Original PR description
If an order in overpaid using bank, no move line is created for the change. Steps to reproduce: ------------------- * Make an order, add a customer * During payment, select invoice, pay more than the…
If an order in overpaid using bank, no move line is created for the change. Steps to reproduce: ------------------- * Make an order, add a customer * During payment, select invoice, pay more than the order amount with bank pm * Validate * Close register * Check customer > Observation: It says we owe the customer money, although change was given. Why the fix: ------------ Since this fix: https://github.com/odoo/odoo/commit/2c4764f111eec154375d94eb7052a12c470a513d the change gets deducted from cash payment method. However the use case where there would not be any cash payment used was not taken into account. The previous fix was removing the change from the payment methods to subtract its amount from any cash payment but in the case where there's none nothing is done with it. Indeed it sometimes happen to pay a bit more in card to get some cash out. Currently, in this case, the change is just omitted. opw-5149700 Forward-Port-Of: odoo/odoo#254125 Forward-Port-Of: odoo/odoo#247621
This update resolves an issue where accrual plans were incorrectly blocking the ability to take future leave, even with sufficient balances. The fix prevents the system from over-calculating leave accruals, ensuring users can accurately plan and take future leave as intended. This improves the usability of the time-off management feature.
Original PR description
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be. #…
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be.
# Steps to reproduce:
Go to time off app
* Create a new leave type.
* Create a new accrual plan with:
- one milestone :
- 2 days accrued per month
- Cap: 10 days
- start accruing 1 days after
- No expiration
- Carry over: All
* Create and validate a leave allocation
- 1 year ago
- new leave type
- new accrual plan
* Take the maximum number of leaves available.
* Advance the computer calendar by 1 year.
* Again, take the maximum number of leaves.
* Advance the computer calendar by another year.
* Try to take a future leave.
-> Issue: It’s not possible to take a future leave, the number of accrued days has stopped increasing. The accrual plan appears blocked.
Objective : The accrual plan should continue to allocate leave days even if leaves have been consumed regularly, as long as the remaining leaves are under the cap.
## Issue
Before going further: the property `leaves_taken` of the `hr.leave.allocation` is supposed to contain the number of leaves this allocation cover until "today".
In the `_test_get_allocation_future_leaves1` added test, in the last line of the test :
`assert_virtual_leaves_equal(self, leave_type_day, 2, self.employee_emp, date='2023-02-01')`
When calling `get_allocation_data` with a `target_date` set in the future, the result is wrong. Here is how it works :
`get_allocation_data`
...
.....`_get_consumed_leaves` (1)
...........`_get_future_leaves_on` (2)
...............`_process_accrual_plans` (3)
....................`_compute_leaves` (4)
.........................`_get_consumed_leaves` (5)
..............................`get_future_leaves_on` (6)
...................................`process_accrual_plans` (7)
**A)** The method **(2)** try to calculate the added number of days each allocation will have on `target_date`. So it creates a copy of the allocation in memory using the 'new' method:
`fake_allocation = self.env['hr.leave.allocation'].with_context(default_date_from=accrual_date).new(origin=self)`
It will then update it to `target_date` using `_process_accrual_plans` and will return the difference of days between the
updated `fake_allocation` and the current allocation (`self`)
**B)** Before iterating over each accrual date, the `_process_accrual_plans` **(3)** will get the `leaves_taken` property which is a computed field. It will trigger `_compute_leaves`.
**C)** The method **(4)** will call `_get_consumed_leaves`, and so the nightmare begins.
**D)** The method **(6)** will create a second `fake_allocation` based on the origin of the first `fake_allocation` (see **A)**).
**E)** This time, `_process_accrual_plans` **(7)** will also look at the `leaves_taken`, but won't trigger the `_compute_leaves` probably because the current allocation is a `fake_allocation` of a `fake_allocation`, and one property of the `new` method is that `Two new records with the same origin record are considered equal.`. Therefore, the `leaves_taken` is considered to be already computed (but it's not).
So `_process_accrual_plans` read the `leaves_taken` which is 0 (probably the default value of `leaves_taken`), but it should be 20 !
**F)** As the value of `leaves_taken` is wrong, the fake_allocation n°2 is also wrong, and its `number_of_day` is 10 but the `number_of_days` of the origin allocation is 20. So `get_future_leaves_on` **(6)** will return -10 which makes no sense, and all the previous calls computations will be wrong. And the final `virtual_remaining_leaves` value will be 0 instead of 2.
## Source of the issue
In the `_process_accrual_plans` method, for each allocation, `leaves_taken` is only computed once at the start of the loop over the allocation "important" dates (see `nextcall` property of `hr.leave.allocation`). At this moment, the method calculates the `leaves_taken` the allocation will have on the `accrual_date` parameter. Yet, this property can change depending on the date the allocation is on (`nextcall` property) which leads to some issues in the computation of the `allocation.number_of_days`.
## Solution
For each allocation, compute the `leaves_taken` at every iteration trough the values of `nextcall`. BUT, this can trigger an infinite loop as computing `leaves_taken` calls `_get_consumed_leaves` which calls `_get_future_leaves_on`, which calls `_process_accrual_plans` ... To avoid this, this PR add the context variable `precomputed_allocations` (will be converted into a function parameter in master) which will prevent `_get_consumed_leaves` from calling `_get_future_leaves_on` for the allocations already up to date (contained by this very `precomputed_allocations` context variable).
opw-4934391
opw-5226806
Forward-Port-Of: odoo/odoo#239836
Forward-Port-Of: odoo/odoo#250998
Forward-Port-Of: odoo/odoo#243812This pull request focuses on significant performance improvements within the HR module, specifically addressing slow data retrieval and inefficient processes. By optimizing queries and caching mechanisms, the changes reduce loading times and enhance the overall responsiveness of the HR system, leading to a better user experience.
Original PR description
task-6044049 Forward-Port-Of: odoo/odoo#254343
This update fixes an issue where e-invoices uploaded in a specific format (PEPPOL BIS 4a) didn't always correctly populate the customer's information on the invoice. The change adds a fallback mechanism to ensure the partner details are accurately captured, preventing data discrepancies. This ensures invoices are correctly linked to the customer.
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 Forward-Port-Of: odoo/odoo#251808
This update resolves an issue preventing the preview of certain reports, specifically the DIN 5008 layout, in Odoo 19.1+. The problem stemmed from a change removing a global variable used to handle report rendering, leading to incorrect record identification. The fix reverts a recent change to restore this functionality and ensure report previews work correctly.
Original PR description
Under some conditions, it is currently not possible to render the preview of some layouts To reproduce the issue: (Need `l10n_din5008`) 1. Open Settings more times than the number of companies in the…
Under some conditions, it is currently not possible to render the preview of some layouts To reproduce the issue: (Need `l10n_din5008`) 1. Open Settings more times than the number of companies in the database - (We actually need to increase the psql sequence of its table...) 2. Configure your document layout - Layout: DIN 5008 3. Click "Preview Document" Error: an error is displayed: "Missing record: Record does not exist or has been deleted. (Record: res.company(4,), User: 2)" When clicking on _Preview Document_, we are actually requesting `/report/pdf/web.preview_externalreport/4` Where we have both the report name and the `docids` (equal to `4` in the above example). Since we are calling it from the `res.config.settings`, we provide the doc IDs with the ID of the `res.config.settings`. However, the report is based on the `res.company` model: https://github.com/odoo/odoo/blob/2f64f909d2f20cc8c0a8e95ba7d17348b9b015e6/addons/base_setup/views/res_config_settings_views.xml#L90 https://github.com/odoo/odoo/blob/e602fc2279e85b66c9983741df5d84fab42a3c44/addons/web/views/report_templates.xml#L1006-L1010 As a consequence, the mechanism will try to render the report using the company with ID equal to the ID of the config settings, which does not make sense. This is the reason why, at some point, it can lead to a `Missing Record` error. That said, the case is working well on previous versions because we were defining a global `o` variable before rendering the template, cf for instance on Odoo 19, L896: https://github.com/odoo/odoo/blob/1c2e17718e6f2a11d93585f0ea3ba3abee5a4a41/addons/web/views/report_templates.xml#L893-L897 Thanks to that variable, DIN 5008 side, we ignore the `docs`, cf here for instance: https://github.com/odoo/odoo/blob/dae4fd0000080ba6395b370e25d3f13f1becd74e/addons/l10n_din5008/report/din5008_report.xml#L96 On Odoo 19.1+, this global variable has been removed by [1]. This commit is actually the result of a script (cf its description). Since the script hasn't detected the use of `o`, it moved its declaration inside the previous `t-call`, L829: https://github.com/odoo/odoo/blob/e602fc2279e85b66c9983741df5d84fab42a3c44/addons/web/views/report_templates.xml#L827-L830 This was a mistake since the global variable is sometimes used. Long story short, the script didn't see the dynamic `t-call` inside the template of `web.external_layout`: https://github.com/odoo/odoo/blob/e602fc2279e85b66c9983741df5d84fab42a3c44/addons/web/views/report_templates.xml#L758-L761 We have therefore decided to revert this part of the commit and apply the same logic to its siblings `preview_internalreport` and `preview_layout_report` [1] https://github.com/odoo/odoo/commit/b7ec60d68c6ee23f7684960e33e5bd6290c9d829 OPW-5951003
This update resolves an issue where invoices generated for Hungarian businesses using the UBL format were being rejected by the NAV system. The fix automatically constructs the VAT number from the Hungarian Tax Number (Adószám) when the country code prefix isn't present, ensuring invoices meet regulatory requirements and can be successfully submitted.
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