Daily updates from Odoo
Monday, February 23, 2026
17 changes · 17.0
Enhancements to existing features
This update adjusts the Romanian tax reporting within the Enterprise module to align with recent changes in the Core Enterprise (CE) version. The update removes outdated tax codes and adds new ones, ensuring accurate reporting for Romanian businesses. This change improves the reliability of financial data.
Original PR description
Some taxes were no longer needed in CE, so they needed to be removed task-5411745
This update modernizes invoice formats for French, German, and Belgian customers, aligning with new regulatory standards for Factur-X and ZUGFeRD. It clarifies invoice types (ZUGFeRD vs. XRechnung) based on business type and customer location, improving clarity and compliance. The changes also update default invoice formats to PDF/A-3 for these regions.
Original PR description
Updating the FacturX format (France)/ ZUGFeRD format (Germany) to respect the new norms: Factur-X 1.07.3 EXTENDED and ZUGFeRD 2.3.3 EXTENDED. Add the differentiation between these two formats in the customer interface, even if they point to the same value in the code. It clarifies things for the customer, things are called by their name. Also, in Germany, for B2B invoices (peppol EAS = 9930), use ZUGFeRD, but for B2G invoices (peppol EAS = 0204), use XRechnung. Adaptation of the default values in the partner form according to this statement. For French and German companies that are sending invoices to French, German or Belgian customers, changed the default format of invoice sent to be compliant to PDF/A-3 norms. task-5266286 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update simplifies the process of downloading attachments from account moves like invoices and vendor bills. Now, all related attachments – including PDFs, XML files, and mail thread attachments – are automatically bundled into a single ZIP file for easy download, eliminating the need to download individual files.
Original PR description
before: - In v17, account moves (invoices, vendor bills, etc.) did not provide any ZIP export. - Users wanting to download move attachments (e.g. for vendor bills) had to download each file individually. after: - Add an Action on account moves to export attachments as a ZIP archive. - The ZIP contains all attachments linked to the move (PDF, XML, and any other files present in the mail thread), not only the report PDF. - The action is available for all move types (customer invoices, vendor bills, journal entries, etc.) task-5232551 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update fixes a bug that occurred when the VIES service returned invalid XML, causing errors in VAT number validation. By catching a broader range of exceptions from the 'zeep' library, the system now handles these errors gracefully, preventing tracebacks and ensuring accurate VAT checks. This resolves an issue impacting OCR invoice refresh functionality.
Original PR description
Catch all `zeep` exceptions instead of only `zeep.Fault`. On 14th of February 2026, the VIES service wasn't working properly, they were returning invalid XML in their response. This caused the `check_vies` call to raise a `zeep.XMLSyntaxError` which wasn't caught, causing a traceback every time VIES was used to validate a VAT number. opw-5938723 (OCR couldn't be refreshed on an invoice because it tried to create a partner from its VAT number and it couldn't be checked with VIES).
This update fixes an error in how leave balances are calculated when simulating accruals across carry-over dates. Previously, the system incorrectly reported negative balances. The fix precomputes leave consumption to avoid a circular dependency, ensuring accurate balance calculations for employees taking leave.
Original PR description
__Problem:__ When simulating accruals across a carry-over date, the system showed a wrong available balance. 1. Create an accrual plan: - 1 day granted at the beginning of each month - reset at the…
__Problem:__
When simulating accruals across a carry-over date, the system showed a wrong available balance.
1. Create an accrual plan:
- 1 day granted at the beginning of each month
- reset at the start of the year (carry-over reset)
2. Enable _Allow Negative_ on Paid Time Off.
3. Create a validated allocation starting at the beginning of the year.
4. Take 11 days of leave at the end of the year, approve and validate it
5. Cross the carry-over (Jan 1), then check balance on __Feb 1__:
- __Expected:__ available 1
- __Current:__ available −9
__Root cause:__
- Circular dependency between `leaves_taken` compute and future accrual simulation:
`_get_future_leaves_on()` → creates `fake_allocation` → triggers
`leaves_taken` → `_compute_leaves()` →
`employee._get_consumed_leaves()` → `_get_future_leaves_on()` again.
→ Infinite recursion / wrong value injected.
__Fix:__
- Precompute and inject the correct `leaves_taken` value when building the `fake_allocation` before processing accrual plans through a direct helper `_get_leaves_taken_in_period(target_date)` to compute leaves consumed up to a given date for a single allocation, without recursion.
- opw-4918619This update resolves a bug that caused the lunch ordering tour to fail when a user quickly navigated to a record before the necessary filters were applied. Specifically, the 4 Formaggi meal was incorrectly selected instead of the intended Aaron's Pizza option. This ensures a smoother and more reliable user experience for ordering lunch.
Original PR description
When ran on a fast enough computer, we clicked on a record before the filter has been applied. In practice, the 4 Formaggi meal was selected instead of Aaron's Pizza runbot-233159
This update resolves a random failure within the website editor's tour feature. The issue stemmed from inconsistencies in how the tour service triggered events compared to real user interactions. Adding a simple delay ensures the system correctly detects the necessary actions, preventing the tour from prematurely ending.
Original PR description
Steps to reproduce
==================
Run the test test_15_website_link_tools a bunch of times. It will eventually fail.
It happens every time if we add the following step after the "Reselect the first image" or the "Re-select image." step:
```js
{
trigger: "body",
run: async function() {
const { promise, resolve } = Promise.withResolvers()
setTimeout(resolve, 500)
return promise
}
},
```
It will fail when checking if the link toolbar is present
Cause of the issue
==================
In 17.0, the tour service doesn't trigger exactly the same events as a real user.
In this case, a selectionchange event is trigger causing the linkpopover to disappear
https://github.com/odoo/odoo/blob/6f7baa97db91f9a447257c3762febf4bd8a04800/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js#L2963-L2977
Solution
========
We can set and focus the selection on the after clicking on it.
runbot-237703This update fixes inaccuracies in Bulgarian tax names and adjusts the default purchase tax rate from 20% PTC to 20% FTC, aligning with current Bulgarian regulations. This ensures accurate tax calculations and reporting for Bulgarian businesses using the Odoo system.
Original PR description
Fixing incorrect tax names and changing the default purchase tax to 20% FTC instead of 20% PTC. task-5935754
This update fixes an issue where the payment term for Mexican CFDI exports was sometimes rendered in English instead of Spanish, leading to potential duplicate filings with the SAT. By explicitly setting the Spanish context, this change guarantees consistent and compliant CFDI XML generation, preventing errors and streamlining the export process.
Original PR description
The CFDI 4.0 field CondicionesDePago is derived from the payment term name, but its rendered value depends on the language context active at XML generation time. Even when the user language is…
The CFDI 4.0 field CondicionesDePago is derived from the payment term name, but its rendered value depends on the language context active at XML generation time. Even when the user language is Spanish, this field may still be rendered in English (e.g. "Immediate Payment") due to context loss during the CFDI rendering process or during XML regeneration. This behavior becomes especially problematic in scenarios with PAC intermittency. A stamping request may be successfully processed by the SAT but time out in Odoo, and a subsequent retry can regenerate the CFDI using a different language context. As a result, two CFDIs with identical fiscal data but different textual content (English vs Spanish) can be generated, potentially leading to duplicated CFDIs registered in the SAT. To ensure deterministic and compliant XML generation, the payment term name is now explicitly evaluated under the es_MX context when rendering the CFDI. This guarantees stable Spanish content for Mexican CFDI textual fields, regardless of user language or transient context changes during the EDI flow. This follows the same rationale as odoo/enterprise@f75a04fa954d, where a lost language context during XML rendering caused inconsistencies between the XML and the expected Mexican CFDI content. Forward-Port-Of: odoo/enterprise#105588
This update corrects a discrepancy in the Romanian tax reports to align with the latest government regulations. Specifically, VAT rates and certain tax amounts have been updated to reflect the current 19-21% and 5%/9%/11% structures. Inactive taxes were also adjusted to ensure accurate report generation.
Original PR description
Romanian VAT has increased from 19% to 21% and from 5%/9% to 11%, some taxes were added previously to the module but they were not reflected in the tax report, also other taxes were missing in order for the report to replicate the current up to date version issued by the romanian government.
This update fixes an issue where lot numbers weren't consistently displayed in POS sales orders when products were tracked by lot and stored in multiple locations. The fix ensures that the correct lot number is accurately reflected for all product lines within the order, improving inventory accuracy and order fulfillment. It also addresses a related issue with stock movement processing during POS closure.
Original PR description
When opening an SO in POS that has a product tracked by lot that is split into several location, the lot number will only appear in one of the line and not the others Steps to reproduce:…
When opening an SO in POS that has a product tracked by lot that is split into several location, the lot number will only appear in one of the line and not the others Steps to reproduce: ------------------- 1. Create a Product A tracked by lot, create lot 111 and add 1 unit to location A and another one to location B 1. Create a sales order 2. Add two units of the product to the sale order 3. Confirm the sales order 4. Open the transfer, make the transfer retrieve the product from several location with the same lot. 5. Save the transfer 6. Open the sales order in POS 7. Load the SN/lots -> Two line of qty 1 appear for the product A but only the first one has the lot number Additional Issue: 8. Change the number of the product for the first line to 2 and erase the second line 9. Confirm and Pay 10. Close POS 11. Open move lines for this product (Inventory>product>In/out) -> It moves 2 product from one location (when there is only product) Observation: ------------- When loading the SO in POS, we will retrieve the SO: https://github.com/odoo/odoo/blob/cb1f5d9c6db64b9ace9b7aa46bd6f94e4462176b/addons/pos_sale/static/src/app/order_management_screen/sale_order_management_screen/sale_order_management_screen.js#L104 While retrieving the SO, we will also retrieve the SOL, with additional information: https://github.com/odoo/odoo/blob/d9b2e5ee730a4e79586bfd3f09adfb794d2dc1f3/addons/pos_sale/models/sale_order.py#L79 -> Issue is that when several moves_line have the sale lot_id.name, their quantity will be overwritten. Addition Issue : When closing pos, all the move will be processed, when processing those moves, the origin only check if the quantity is more than 0 and not if there is enought units. https://github.com/odoo/odoo/blob/cb1f5d9c6db64b9ace9b7aa46bd6f94e4462176b/addons/point_of_sale/models/stock_picking.py#L293-L297 opw-5347992
This update allows branch companies to see and select contacts owned by their parent company when creating invoices or vendor bills. Previously, a branch company could only see contacts owned by itself or those without a company assigned. This change resolves a limitation in the multi-company hierarchy functionality.
Original PR description
Currently, when operating in a branch company, contacts belonging to the parent company are not visible in the partner dropdown on Invoices or Vendor Bills. ### **Steps to reproduce:** 1) Create a…
Currently, when operating in a branch company, contacts belonging to the parent company are not visible in the partner dropdown on Invoices or Vendor Bills.
### **Steps to reproduce:**
1) Create a multi-company hierarchy (Company A -> Branch B).
2) Create a contact owned by Company A.
3) Switch the current company to Branch B.
4) Go to Accounting > Customers > Invoices and create a new invoice.
5) Try to select the contact created in step 2.
### **Current/Buggy Behavior:**
The contact does not appear in the search results.
### **Expected Behavior:**
The contact should be selectable.
### **Root Cause:**
since commit https://github.com/odoo/odoo/commit/67169c42061cb51bc68f6c74f0674a670dd04f58,
the partner model supports the standard
`check_company=True` mechanism, and record rules were updated to allow
branches to access partners of their parent company.
However, the `partner_id` field on the `account.move` form view still
retained a explicit domain: `[('company_id', 'in', (False,
company_id))]` as shown at [1].
This domain overrides the standard `check_company` behavior.
due to which it restricts the selection to partners owned by the current company
(the branch) or partners with no company set. It explicitly excludes
partners owned by the parent company.
### **Fix:**
Remove the domain at [1],
This allows the field to rely on the standard `check_company=True`
logic, which correctly handles the multi-company hierarchy and allows
branches to select parent company partners.
[1]- https://github.com/odoo/odoo/blob/6b7b83449739932aa8420ef8fcd888116e3c0f8a/addons/account/views/account_move_views.xml#L896
**opw-5484611**This update corrects a bug where the carousel image navigation wasn't functioning correctly in RTL (Right-to-Left) languages like Arabic. By adding a specific HTML attribute, the carousel now correctly displays the next and previous images based on the language direction, ensuring a consistent user experience across different languages.
Original PR description
Some libraries expect to find the language direction on the HTML element (e.g. Bootstrap). As we didn't set it, there were some issues. For instance on the website: - set the website language to some RTL language (e.g. Arabic) - drop an image gallery snippet and save - navigate with the keyboard to the carousel and start using the arrows to switch images => Pressing left should show the _next_ image, and pressing right should show the _previous_ image (contrary to LTR languages). This is illustrated by the image indicators at the bottom of the carousel (the 1st image is on the right, the last image on the left). But without `dir="rtl"` on the HTML element, the arrows keep their LTR behavior: pressing left goes to the previous image, and right to the next image. task-5109547
This update ensures that NACHA payment files accurately reflect the actual account holder's name, rather than the customer's name in Odoo. Prioritizing the bank account holder's name improves payment processing accuracy and compliance with NACHA standards.
Original PR description
The NACHA entry detail was using the partner's name (res.partner.name) for the Individual Name field. This should instead prioritize the Account Holder Name (acc_holder_name) from the bank account, as this reflects the actual name on the bank account which may differ from the partner's name in Odoo. The code now uses bank.acc_holder_name if set, and falls back to payment.partner_id.name if not set.
This update resolves an issue where users received a generic error message when attempting to print resumes with invalid templates. The fix adds detailed tracebacks to the error message, providing developers with the necessary context to quickly identify and resolve template problems. This improves the user experience and streamlines troubleshooting.
Original PR description
Currently, when a user tries to print a resume with an invalid template there’s no traceback to show what went wrong. **Steps to produce:** * Install `hr` with demo data * Modify the view…
Currently, when a user tries to print a resume with an invalid template there’s no traceback to show what went wrong. **Steps to produce:** * Install `hr` with demo data * Modify the view `report_employee_cv` by adding `<div t-if=o.no/>` * Print resume of any employee **Observed Behavior:** Currently it only shows the error in [1], with no context or traceback to explain what went wrong. **Root cause:** * This happens because the route doesn’t include the website parameter. Without it, the system treats the route as non–front end [2], so the error handler never reaches [3].That means [4] never loads the templates [5], and the browser just gets a plain response at [6]. **Solution:** * Catching and raising UserError shows appropriate traceback. **Before:** <img width="1606" height="796" alt="image" src="https://github.com/user-attachments/assets/d5432fbf-d016-46a9-bade-8e8408848c66" /> **After:** <img width="1832" height="928" alt="image" src="https://github.com/user-attachments/assets/6f0413ca-a82a-487d-888f-81be6f0fab03" /> [1]: https://drive.google.com/file/d/1qJLkFGw4bEclqKihdUI-4bjJofdFArEc/view?usp=sharing [2]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L386 [3]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L611 [4]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L573-L576 [5]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/views/http_routing_template.xml#L139 [6]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L575 Related: https://github.com/odoo/enterprise/pull/100142 opw-5167898
This update fixes a problem where users received a generic error message when generating PDF payroll reports with invalid templates. Now, the system displays a detailed traceback, making it easier to identify and resolve the underlying template issues. This improves the user experience and streamlines troubleshooting.
Original PR description
Currently, when a user tries to print a PDF report with an invalid document layout template, there’s no traceback to show what went wrong. **Steps to produce:** * Install payroll with demo data. *…
Currently, when a user tries to print a PDF report with an invalid document layout template, there’s no traceback to show what went wrong. **Steps to produce:** * Install payroll with demo data. * Settings > Configure Document Layout then Edit Layout * Add non-existent field `<div t-if='o.no'/>` * Payroll > All payslips > print any payslip **Observed Behavior:** * Currently it only shows the error in [1], with no context or traceback to explain what went wrong. **Root cause:** * This happens because the route doesn’t include the website parameter. Without it, the system treats the route as non–front end [2], so the error handler never reaches [3].That means [4] never loads the templates [5], and the browser just gets a plain response at [6]. **Solution:** * Catching and raising UserError shows appropriate traceback. **Before:** <img width="1601" height="507" alt="image" src="https://github.com/user-attachments/assets/f7f208f0-cdd7-410e-87e7-32a9651df9d8" /> **After:** <img width="1847" height="928" alt="image" src="https://github.com/user-attachments/assets/c73522d6-2632-422b-b1d1-234e6c61ed2e" /> [1]: https://drive.google.com/file/d/1qJLkFGw4bEclqKihdUI-4bjJofdFArEc/view?usp=sharing [2]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L386 [3]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L611 [4]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L573-L576 [5]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/views/http_routing_template.xml#L139 [6]: https://github.com/odoo/odoo/blob/e4e2dca73213c33c487033dd404a7ca335960a66/addons/http_routing/models/ir_http.py#L575 Related:https://github.com/odoo/odoo/pull/237262 opw-5167898
This update fixes an issue where the names of Ecuadorian localization regimes didn't comply with government regulations. The change ensures all names are in Spanish, as required for electronic invoices submitted to the government, regardless of the user's language settings. This ensures accurate and compliant invoicing for Ecuadorian businesses.
Original PR description
[FIX] l10n_ec_edi: fiscal localizations name The name of the regimes for the Ecuadorian localization does not respect the government requirements Steps to reproduce: 1. Install l10n_ec_edi module 2. Go to Settings > Invoicing > Ecuadorian Localization 3. In Electronic Invoicing > Regime, the names of the regimes do not respect government requirements Solution: Change the name of the fiscal localizations to respect the requirements Add a computed field used to map the name of the regime to the technical name of the regime used in SRI documents We write them in Spanish because we always want the name of the regime to be in Spanish in the XML invoice sent to the government, even if the user didn't install any other language. opw-5221871