Tuesday, January 27, 2026
12 changes · 19.0
New functionality added to Odoo
This update introduces a new module to help companies prepare reports aligned with the EU's CSRD and VSME frameworks. It leverages existing Odoo data (like emissions and employee information) and AI suggestions to streamline the reporting process, improving sustainability disclosures for investors and stakeholders.
Original PR description
In this PR, we add the possibility to create and manage a complete CSRD/VSME report, integrated with AI, knowledge, survey and HR. The Corporate Sustainability Reporting Directive (CSRD) is a legal…
In this PR, we add the possibility to create and manage a complete CSRD/VSME report, integrated with AI, knowledge, survey and HR. The Corporate Sustainability Reporting Directive (CSRD) is a legal framework in the EU that requires companies to report on their sustainability performance. It aims to standardize ESG reporting across the EU and make the information more comparable and reliable for investors and other stakeholders. On the other hand, the Voluntary Sustainability Reporting for Micro and Small Enterprises (VSME) is a framework designed to support smaller companies in reporting on their sustainability performance. It encourages clear, comparable, and meaningful ESG disclosures while remaining proportionate to the size and capacity of the business. Our reporting feature facilitates the steps involved in preparing a CSRD/VSME report by using the data we already have in Odoo, such as emissions (Scope 1, 2, 3), employee data, supplier and client information, or fleet metrics. As well as using AI to make suggestions, and integrating knowledge articles and surveys. More precisely, the feature is composed of two main models: - A new model (`esg.metric)` that is only used if the CSRD reporting is enabled (and only used in the context of CSRD reporting). It is linked to an ESRS data point (either Environmental, Social or Governance category) and can be of different types (Positive/Negative Impact, Risk or Opportunity). It is used to assess if a topic is material or not (Double Materiality Assessment), depending on the impact severity and financial severity scores. As well as scores obtained from the stakeholder reviews (we get those scores from surveys that have been completed, the surveys are sent with the action "Stakeholder Review"). To help the user to create relevant metrics, we added an AI feature allowing to generate suggestions of metrics. Provided that the user gives a description of the company (size, revenues, activity, etc) to give as much context as possible to the AI prompt (see action "AI Suggest"). - A new model (`esg.report`) where you can specify the type of the report (CSRD or VSME), the dates (reporting date and base reference date), and additional information about the company. Once created, the report is linked to a knowledge article that contains the template of a complete CSRD/VSME report that you can edit, fold/unfold sections, add content, etc. When printing it to PDF, a lot of information is automatically filled in (data about your employees, accounting data, etc), including the carbon report, dynamic tables. That is done by replacing placeholders from the knowledge article when generating the PDF (an appendix includes all available placeholders with a small explanation for each). For CSRD reports only, there is the ability to automatically fold/unfold the ESRS sections of the articles depending on whether the data points we get from the metrics are material or not (see action "Update Materiality"). For VSME reports only, there is a "Basic Module + Comprehensive Module" type that will include additional sections (C1-C9). Note that you can also load them manually from the root article with the "Load Template" action. task-5172829
Enhancements to existing features
This update enhances the system administrator panel by allowing for more flexible and customizable notifications. Previously, only a single message could be displayed. Now, administrators can configure multiple messages with different alert levels, providing more targeted and informative updates about server maintenance or other critical events.
Original PR description
Tweak #102239 to allow more flexibility and display multiple messages with different alert level.
The ir.config_parameter is sysadmin.message and should be a json loadable. The format shoud be something like this:
{
"replace": false,
"warning_type": "user",
"message": "<div class='alert alert-info'>A maintenance operation is planned on your server on <strong>2026-01-15</strong> between 14h and 15h</div>"
}
Forward-Port-Of: odoo/enterprise#105157Resolved issues and error corrections
This update enhances the monitoring of our AI usage by changing key logs from 'debug' to 'info', making them easier for administrators to track. Additionally, the system now accurately reports token usage from the LLM providers, resolving previous underreporting issues. This provides better visibility and control over AI costs.
Original PR description
In this commit we change some important llm api usage logs from debug to info so they can be more easily monitored by us and database admins. We also change the usage reporting from a naive estimation (which greatly under-reported the token usage) to the actual token usage given to us by the LLM prodivers in the response.
This update addresses a limitation in the account online synchronization process where access tokens expire quickly. We've implemented a new consent token system – a unique, secure identifier linked to the user – to ensure reliable consent management and continued synchronization functionality. This change improves the user experience and stability of the online connection.
Original PR description
In this commit:bf5b7d0 we introduce a message on the account_online_link to be able to manage the consent. (one needed fix in this commit:https://github.com/odoo/enterprise/commit/1c84804fd3f0c0d1d23916b9f6a388616f66ac7e) This commit will change the way we manage the consent since the access token is in fact available only for 30 min, so the link in the chatter would not work. We decided to have a consent token which is a uuid4 encoded in base64 (url safe) and link it to the odoofin user. task-5187621 Forward-Port-Of: odoo/enterprise#105392 Forward-Port-Of: odoo/enterprise#105202
This update corrects a compatibility issue with the Bulgarian National Bank (BNB) exchange rate provider. Since Bulgaria adopted the Euro, the BNB now provides rates in EUR, not BGN. This fix ensures that companies using EUR as their main currency can correctly sync exchange rates, resolving a previous error.
Original PR description
The `_parse_bnb_data` method assumed that the Bulgarian National Bank (BNB) provides exchange rates against BGN (Bulgarian Lev). However, since Bulgaria joined the Eurozone on January 1, 2026, the…
The `_parse_bnb_data` method assumed that the Bulgarian National Bank (BNB) provides exchange rates against BGN (Bulgarian Lev). However, since Bulgaria joined the Eurozone on January 1, 2026, the BNB now provides rates against EUR. This caused the error "Your main currency (EUR) is not supported by this exchange rate provider" when Bulgarian companies with EUR as their main currency tried to sync exchange rates. refs: We can compare the data here from 31 December using the WayBackMachine: https://web.archive.org/web/20251231193558/https://www.bnb.bg/Statistics/StExternalSector/StExchangeRates/StERForeignCurrencies/index.htm Compared to today: https://www.bnb.bg/Statistics/StExternalSector/StExchangeRates/StERForeignCurrencies/index.htm And see the comparison used to be to BGN but is now for EUR Steps To Reproduce: 1. Create a company for Bulgaria with EUR as the main currency. 2. Go to Accounting Settings -> Automatic Currency Rates. 3. Select "[BG] Bulgaria National Bank" as the service provider. 4. Click the sync button. 5. Error appears: "Your main currency (EUR) is not supported by this exchange rate provider. Please choose another one." The fix updates the base currency from BGN to EUR, matching the current BNB XML format which now provides rates against EUR. Note: Companies with BGN as main currency will now get the same error, which is expected since the BNB no longer provides BGN-based rates. This behavior was discussed and confirmed with the PO. Ticket [link](https://www.odoo.com/odoo/project.task/5483771) opw-5483771 Forward-Port-Of: odoo/enterprise#105074
This update resolves an issue where payment reports were inconsistently using different export formats (NACHA or localization-specific). The fix ensures that payment reports now automatically use the correct format based on the company's localization, improving report accuracy and usability for users. This change also includes added testing.
Original PR description
\* = l10n_{ae, au, ch, in, sa, us}_hr_payroll + hr_payroll_account_iso20022
Issue:
The current behavior looks deterministic: when clicking on "Create Payment Report" it -sometimes- shows the current company's export format by default, other times it shows the "NACHA" type. Or it could be the last installed module's export format value for the other companies.
Solution:
I fixed it in this PR: https://github.com/odoo/enterprise/pull/93683 and now backporting the changes to version 18.0
task-5189295
Forward-Port-Of: odoo/enterprise#104086
Forward-Port-Of: odoo/enterprise#100126This update fixes a bug in the Austrian Tax Report where VAT from vendor bills was incorrectly subtracted instead of added. The change adjusts a key formula to accurately reflect the total, aligning with previous versions and ensuring correct tax reporting. This ensures accurate tax calculations for Austrian businesses.
Original PR description
### Issue: In 19.0, VAT from vendor bills was subtracted from the total in the Austrian Tax Report, instead of being added ### Cause: The expression `tax_report_line_l10n_at_tva_line_7_total` uses an incorrect formula: `<field name="formula">AT_0004.vat - AT_0005.vat + AT_090.vat</field>` It should instead be: `<field name="formula">AT_0004.vat + AT_0005.vat + AT_090.vat</field>` This matches the behavior of previous versions In 18.0, there was no aggregated AT_0005 line All values were summed together, which effectively resulted in the same total ### Steps to reproduce: - Install `l10n_at_reports` - Switch to AT Company - Open the Tax Return and note the last line value for the current month - Create and confirm a vendor bill with 20% VAT - Compare the new value in Tax return Before the fix, the total line was decreased instead of increased opw-5349445 Odoo PR: https://github.com/odoo/odoo/pull/244471
This update fixes an issue where negative lines on invoices generated for Ecuador (l10n_ec) were not correctly processed in the XML format. The change aligns the handling of these lines with Mexico (l10n_mx), ensuring accurate discount application and preventing rounding errors that could impact invoice accuracy. This improves the reliability of financial reporting.
Original PR description
In **l10n_ec**, negative lines are not accepted in the XML. They must be dispatched as discounts on positive lines. The dispatching logic implemented in `60e1b41734f76a2d9268edc41286462a9d01a501` can…
In **l10n_ec**, negative lines are not accepted in the XML. They must be dispatched as discounts on positive lines. The dispatching logic implemented in `60e1b41734f76a2d9268edc41286462a9d01a501` can cause rounding issues when the decimal accuracy for `price_unit` is increased. ## Steps to reproduce With **l10n_ec**: 1. Change the decimal accuracy to 6 digits. 2. Set the rounding method to *global rounding*. 3. Create an invoice with the following lines: | Quantity | Price | Taxes | |-----------|----------|-----------| | 20 | 1.4235 | VAT 0% G | | 20 | 1.6425 | VAT 0% G | | 20 | 1.2337 | VAT 0% G | | 20 | 1.2337 | VAT 0% G | | 20 | 1.4235 | VAT 0% G | | 6 | 3.747768 | VAT 15% G | | 6 | 3.747768 | VAT 15% G | In the generated XML, some product lines show a `descuento` of `0.01` or `-0.01`. This happens due to rounding differences in how the `descuento` is computed in the `common_details_info_template` from **l10n_ec_edi**: format_num_2(line_edi_values['price_discount'] + abs(line.balance) - line_items[1]['base_amount']) where `line.balance` and `line_items[1]['base_amount']` can differ by 0.01 due to global rounding applied during tax aggregation, and that difference must be redistributed somewhere. This commit changes how negative lines are dispatched onto positive ones, aligning the behavior with **l10n_mx**. Instead of using `tax_details_per_record` to build the XML, we now use `base_lines`, where the negative lines have already been distributed. opw-5128612 Forward-Port-Of: odoo/enterprise#104659 Forward-Port-Of: odoo/enterprise#97337
This update resolves an issue where Stripe-created expense records were being duplicated, causing data inconsistencies and errors. The fix prevents duplication and streamlines the demo setup by skipping Stripe KYC steps, improving the user experience. It also ensures demo buttons are always visible.
Original PR description
Prevent expenses automatically created by Stripe Issuing to be duplicated. Currently, it adds a lot of noise on customer dbs. The payment method is duplicated and it can lead to errors (eg: employee submit duplicatas instead of the original expenses. The automatic reconciliation doesn't happen afterwards) task-5246475
This update fixes an issue where the VoIP ringtone played incorrectly across multiple Odoo tabs. The system now uses a central SharedWorker to intelligently select a tab to play the ringtone, ensuring it only plays once and addressing potential problems with connection loss or tab inactivity. This enhances the overall reliability of incoming call notifications.
Original PR description
Each Odoo tab establishes a WebSocket connection with the VoIP provider. This causes problems with incoming calls: each tab receives the notification, which leads to the associated callbacks being…
Each Odoo tab establishes a WebSocket connection with the VoIP provider. This causes problems with incoming calls: each tab receives the notification, which leads to the associated callbacks being called as many times as there are open tabs. This used to be particularly annoying with the ringtone, which would play in unison. To solve this problem, we decided that only the "main tab" should be responsible for playing the ringtone. Since there can only be one main tab at a time, there can only be one ringtone at a time. Problem solved. This seemed to be an easy and effective solution. However, we were informed that sometimes the call wouldn't ring at all 🤬 This called the reliability of the system into question. What would happen if: - The main tab loses the WebSocket connection? - The main tab is throttled? - The main tab was never interacted with, preventing us from playing audio? - The notification arrives after the main tab is killed and before a new main tab is elected? This commit attempts a new approach ⋆✴︎˚。⋆ All tabs receiving incoming call notifications will now send a message to a central authority—The _SharedWorker_ 🙀—along with information about whether or not they can play audio. The SharedWorker then selects the first tab that can play audio and assigns it the task of playing the incoming ringtone. This is expected to solve the problems mentioned above, as it guarantees that the "player tab" is a tab that: - effectively received the incoming call notification - is allowed to play audio [Task-5411760](https://www.odoo.com/odoo/project.task/5411760) Backport of https://github.com/odoo/enterprise/pull/104885
This update resolves a JavaScript error that occurred when opening the Shop Floor through the replenishment/forecast flow. The fix ensures the application name is correctly identified, preventing a traceback and allowing users to consistently access the Shop Floor functionality. This improves the reliability of the manufacturing process.
Original PR description
Opening the Shop Floor via the replenishment/forecast flow can raise a js traceback. **Steps to produce:** - Install `mrp` module. - Enable `multi-step routes` from the settings. - Inventory >…
Opening the Shop Floor via the replenishment/forecast flow can raise a js traceback. **Steps to produce:** - Install `mrp` module. - Enable `multi-step routes` from the settings. - Inventory > Configuration > Warehouse Management > Routes. - In Manufacture route, make sure route is Applicable On `products`. - Inventory > Products > Products > New. - Click on forcasted button on product > Click on replenish button > Confirm. - Click the Manufacturing Order shown in the notification. - Confirm the MO and click Shop Floor. **Issue:** A JavaScript error occurs: `TypeError: Cannot read properties of null.` **Root cause:** The Shop Floor view relies on the menu service to determine the current application name by calling `this.menu.getCurrentApp().name`. When the Shop Floor is opened from the replenishment/forecast flow, the navigation occurs through action-based triggers rather than through the main menu. As a result, no menu selection is performed and `setCurrentMenu()`[1] is not executed beforehand.This leaves the current application undefined, causing `menu.getCurrentApp()` to return undefined and leading to a js traceback when `.name` is accessed. [1]: https://github.com/odoo/odoo/blob/c646cb61d0752250b2600413d6d63deabd1d3e6d/addons/web/static/src/webclient/menus/menu_service.js#L57-L64 simillar fix : https://github.com/odoo/enterprise/pull/93043 Note: A tour is possible but unnecessary for this small use-case. opw-5462965 ---
This update corrects a technical issue preventing proper validation of vendor bills on ARCA. The 'CodAutorizacion' field was incorrectly named, causing errors and preventing the system from correctly processing invoices. This ensures accurate bill validation and avoids disruptions to the accounting process.
Original PR description
In this commit https://github.com/odoo/enterprise/pull/103370/changes#diff-2459e118c605cf039bb94c62561285ad753b6a27c571f10a25547ee9b01aa318R289 where a refactor has been made, the field 'CodAutorizacion' was left as 'invCodAutorizacion' on _l10n_ar_edi_get_request_data_verify. This leads to errors when validating vendor bills on ARCA, since the organism could not find the required field. <img width="640" height="163" alt="image" src="https://github.com/user-attachments/assets/74a0cdc6-c007-474c-a67b-fd12d484838f" /> Forward-Port-Of: odoo/enterprise#105362