Monday, June 15, 2026
19 changes · 19.0
Enhancements to existing features
The PDF shown for UBL/CII electronic invoice documents now has a more polished header and footer. It also clearly marks the document as generated by Odoo and notes that it is not an official document, helping avoid customer confusion.
Original PR description
The previous UI was a little bit raw. To improve the client experience, we made the following changes: - Modify an inherited internal layout to improve header and footer. - Add a pill that says "Generated by Odoo". - Add a sentence mentioning that it is not an official document. Task-6132980 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260393
Swedish company records can now derive the organization number directly from the VAT number when applicable. This reduces manual data entry and helps keep Swedish business registration details consistent with official VAT formatting.
Original PR description
Organization number is part of the VAT number Official reference: https://www.skatteverket.se/foretag/moms/kopavarorochtjanster/inkopfranandraeulander/kopavarorfranandraeulander.4.3a7aab801183dd6bfd380005738.html > I Sverige börjar alla VAT-nummer med bokstäverna SE (landskoden) och avslutas med siffrorna 01. Om du har en enskild firma följs landskoden av de 10 siffrorna i ditt personnummer. Om du har ett bolag eller en förening följs landskoden av de 10 siffrorna i organisationsnumret. VAT-numret skrivs utan bindestreck. which translates to > In Sweden, all VAT numbers begin with the letters SE (the country code) and end with the digits 01. If you are a sole proprietor, the country code is followed by the 10 digits of your personal identification number. If you are a corporation or an association, the country code is followed by the 10 digits of your organization number. The VAT number is written without a hyphen.
Resolved issues and error corrections
Vendor bill imports from UBL files no longer fail when the supplier or customer identifier field is present but empty. This prevents an import crash and helps businesses process invoices from partners whose e-invoice files omit that optional value.
Original PR description
**Description:** Importing a UBL file (vendor bill) fails if it contains an empty "EndpointID" node. It assumes the node always contains text content to sanitize, but if it is empty, it crashes with: AttributeError: 'NoneType' object has no attribute 'strip'. **Steps to reproduce:** 1. Import a UBL as a bill, with an empty EndpointID node of the other party. 2. The import fails with the AttributeError. opw-6246515 Forward-Port-Of: odoo/odoo#269028
Code cleanup and technical improvements
Accounting list view code was reorganized so shared behavior can be reused across journal entries and bank statements. This reduces duplicated logic and removes outdated special-case handling, making future accounting updates easier and safer to maintain.
Original PR description
Made some generic JS classes that can be used between account move and account bank statement and removed some if statements that are no longer needed from account_tree controller because they were used to bypass default behavior if used by a model other than the intended one. This issue was fixed in: https://github.com/odoo/enterprise/pull/117476 task-5892419
Employee version timelines now refresh more reliably after versions are created or removed. This avoids delayed refresh behavior and helps HR users see up-to-date information without unnecessary page rendering work.
Original PR description
A useEffect was added to clear the cache of the versions in case of generation or removal of versions. This is not the best as it waits for everything to be rendered and applied to the DOM to trigger a reload. The alternative is to add a context to the widget and to the orm.searchRead, to trigger a cache miss on version change. task-6289891
Quotations using the DIN5008 layout now correctly show the recurring plan for subscription orders. This prevents customers from receiving subscription quotes with missing billing schedule information.
Original PR description
This revert the previous commit that was hiding too much elements. (#261727) When generating a quotation for a recurring plan, if the quotation uses the DIN5008 template, the recurring plan is not shown in the report. Steps to reproduce: ------------------- * Make sure l10n_din5008 is installed * Create a Swiss company * Go to the subscription app and create an order with a recurring plan * Print the quotation > Observation: The recurring plan is not shown in the report. Why the fix: ------------ We add a new scss rule to make sure the recurring plan is always shown in the report. https://github.com/odoo/enterprise/blob/fb2eb6cfdc4527e102dd22321975ab3f0d24b88b/sale_subscription/views/subscription_templates.xml#L7-L23 opw-596021
This fix ensures Overtime Hours work entries are treated as extra hours in HR work entry calculations. It helps keep overtime reporting and related payroll or attendance processes aligned with the intended business rules.
Original PR description
make sure that Overtime Hours entries is concidered as extra hours Task: 6279514 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix makes the live chat chatbot setup test wait properly while a new step form loads after saving. It reduces false test failures under heavy system load, helping keep quality checks stable without changing customer-facing behavior.
Original PR description
When creating chatbot steps, the tour clicks "Save & New" and waits for a fresh empty step form before typing the next one. That wait was done inside a step `run` with `waitFor`, which only polls for 200ms. "Save & New" saves and reloads the parent record, switches the saved record to readonly, then loads a new empty record. Under load this takes more than 200ms, so the wait gives up before the empty textarea appears and the tour fails. Wait for these conditions in the step trigger instead, which uses the regular (much longer) step timeout. https://runbot.odoo.com/odoo/runbot.build.error/237893 Forward-Port-Of: odoo/odoo#270057
This fixes two mobile display issues in the Inbox: an extra arrow shown beside the Expand button and action buttons wrapping awkwardly in the header. The Inbox menu now looks cleaner and remains easier to use on smaller screens.
Original PR description
On mobile, an unwanted caret was displayed next to the message 'Expand' button in the Inbox because the messaging menu itself opens a dropdown, causing any nested Dropdown to automatically display a caret. This commit also fixes the alignment of the Inbox header action buttons, which wrapped onto multiple lines when opening the messaging menu on mobile while the Inbox tab was already selected. In this case, the `AutoresizeInput` width was computed at its maximum size, leaving insufficient space for the header action buttons and causing them to wrap onto multiple lines. Task-[6244177](https://www.odoo.com/odoo/project/1519/tasks/6244177)
Users can now rename multiple projects from the project list without triggering an error. The change keeps related analytic account names in sync using the new entered name, improving reliability for bulk project updates.
Original PR description
Currently, an error will occur when user multi edits name of projects. Steps to replicate: - Install `project` and open projects. - From the list view select multiple projects and edit their name.…
Currently, an error will occur when user multi edits name of projects.
Steps to replicate:
- Install `project` and open projects.
- From the list view select multiple projects and edit their name.
Error:
```
File '/home/odoo/src/odoo/saas-19.3/addons/project/models/project_project.py', line 754, in write
analytic_account_to_update.write({'name': self.name})
File '/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py', line 1728, in __get__
record.ensure_one()
File '/home/odoo/src/odoo/saas-19.3/odoo/orm/models.py', line 5341, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: project.project(8, 9, 10)
```
Cause:
- As multiple records were changed at the moment, `self` had multiple recordsets and trying to access `self.name` [1] causes this error.
Solution:
- Avoided accessing `self.name` on a multi-recordset during multi-edit.
- Updated analytic account names using the name recieved in the vals.
[1]: https://github.com/odoo/odoo/blob/a69ec43f490735f639292d116b0207182c5b2581/addons/project/models/project_project.py#L608
sentry-7452096418
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#267620This update resolves a technical issue that prevented users from correctly resizing task pills in the Gantt view when no dependent tasks were involved. The fix ensures the system handles empty rescheduling lists gracefully, preventing a crash and maintaining proper Gantt functionality. This improves the overall stability and usability of the project scheduling feature.
Original PR description
Steps to reproduce: - Create a project with task dependencies enabled - Create a task with planned dates and no dependent tasks - Open the Gantt view - Select Auto-Reschedule (Use Buffer or Keep Buffer) - Shrink the task pill by dragging its right edge to the left Issue: A traceback occurs: ValueError: max() iterable argument is empty Cause: when no dependent task needs to be rescheduled, the candidates is empty and max() is called on an empty list. Solution: Check that candidates exist before computing the maximum deadline from the dependent tasks. task-6268332 Related PR https://github.com/odoo/enterprise/pull/113787
This update resolves an issue where inactive and archived taxes were incorrectly displayed in the bank reconciliation widget. The fix ensures that only active taxes are available for selection, improving data accuracy and preventing users from selecting irrelevant tax codes during reconciliation processes. This enhances the reliability of financial reporting.
Original PR description
### Issue:
When editing a line within the bank reconciliation widget, inactive and archived taxes are incorrectly available for selection
### Cause:
The bank reconciliation edit line form view carried the `{'active_test': False}` context on the `tax_ids` field
This context allowed archived taxes to be loaded and selected during creation and manual edition
### Fix:
Explicitly force `active_test: True` in the view context for the tax field to ensure only active taxes can be searched and selected by the user
### Steps to reproduce:
- Install `account_accountant`
- Create a new tax and set it to inactive
- Go to the Bank Reconciliation widget
- Create a bank statement line
- Set the account to 600000 Expenses
- Edit the line by clicking on the pencil icon
- Open the Taxes selection dropdown
Before the fix, the inactive tax is visible and available for selection by default
opw-6245641This update resolves an issue where demo leave allocations wouldn't correctly update during an Odoo upgrade from 17.0 to 18.0. The fix ensures that demo data is processed correctly, validating leave allocations regardless of the installation method (fresh or upgrade).
Original PR description
Steps: - Install an Odoo 17.0 database with the Indian Payroll module and demo data. - Upgrade the database to 18.0. Issue: - The Indian payroll demo data creates leave allocations and approves them…
Steps: - Install an Odoo 17.0 database with the Indian Payroll module and demo data. - Upgrade the database to 18.0. Issue: - The Indian payroll demo data creates leave allocations and approves them through an XML function call. - During a fresh installation, demo files are loaded in 'init' mode, so the approval function is executed and the allocations move from 'confirm' to 'validate'. - However, during a 17.0 >>> 18.0 upgrade, demo files are loaded in 'update' mode. Odoo automatically loads demo files with 'noupdate=True' from the load_demo() >> load_data() function: - This value is passed to the XML importer and becomes the default noupdate state for the file. Since the demo XML file does not explicitly override this value, the function tag uses 'noupdate=True'. - When the XML parser reaches the approval function, _tag_function() skips its execution because of noupdate = 'True' and mode = 'update' condition. - As a result, the approval function is not executed during the upgrade and the leave allocations remain in 'confirm' state. Subsequent demo payroll data expects validated allocations and fails during loading. Fix: - Explicitly set 'noupdate=0' on the demo XML file. This overrides the default 'noupdate=True' value applied to demo files, making the parser evaluate the section with 'noupdate=False'. - As a result, '_tag_function()' executes the approval method during upgrades, the demo leave allocations are validated in both fresh/new db installations and 17.0 >>> 18.0 upgrade scenarios. runbot error-https://runbot.odoo.com/odoo/error/230430 task-6268381 Forward-Port-Of: odoo/enterprise#119217
A technical issue prevented users with limited time-off permissions from accessing the Attendances Gantt View when viewing leave requests. This fix ensures that the Gantt View correctly displays leave information for all users, regardless of their access rights. The change uses a security enhancement to correctly access necessary data.
Original PR description
Version: - 19.0 Steps to reproduce: - Install Attendances and Time Off - Create an internal user. - Give the user: Attendances Officer access & No Time Off Officer/Manager rights - Create an employee…
Version: - 19.0 Steps to reproduce: - Install Attendances and Time Off - Create an internal user. - Give the user: Attendances Officer access & No Time Off Officer/Manager rights - Create an employee linked to the user. - Configure the employee with a Flexible Working Schedule. - Create and approve a Time Off request for the employee. - Open: Attendances -> Gantt View - Navigate to the month containing the employee's approved leave. Issue: - An access error is raised when opening a month that contains the employee's approved leave. Cause: - In `_handle_flexible_leave_interval`, the code accesses `leave.holiday_id` to read fields such as `request_unit_half`, `request_unit_hours`, and `request_hour_from/to` on the `hr.leave` model. - When the current user has Attendances Officer rights but no Time Off access(rare cases), the ORM access check on `hr.leave` raises an AccessError, even though this read is purely for internal calendar computation and does not expose leave data to the user interface. Fix: - Added sudo() on holiday_id to access the employee's leave details and compute the work interval as expected. Task-6264510
This update resolves an issue in the website editor for renting products where removing the quantity field caused an error. The fix ensures the system gracefully handles scenarios where the quantity field is no longer present, preventing tracebacks and improving user experience. This change was introduced in version 19.0.
Original PR description
Before this commit, the function `setAddQtyInputMax` in `/website_sale_renting_planning/static/src/interactions/website_sale.js` assumes `this.el.querySelector("input[name='add_qty']");` will always return not null but you can remove this field through the website error and cause a traceback.
https://github.com/odoo/enterprise/blob/c1d47899c90fcfa426e1863887111d3ea9f6f15e/website_sale_renting_planning/static/src/interactions/website_sale.js#L18-L39
Steps to reproduce issue:
Runbot 19.0
Open renting -> Products
Select a product (preferably one created by default runbot setup) Click the smartbutton to go to this products web page Open the website editor
Click Edit
Under the styles tab, de-select the quantity field See error message
**Only happens in 19.0**
Introduced in https://github.com/odoo/enterprise/commit/89962571c246caf05e669bb63ad933e67e74ab61
opw-6294612This update resolves a technical issue where the Urbanpiper order information screen incorrectly displayed customer details even after the customer was removed. The fix ensures that customer information is only shown when a valid customer is associated with the order, improving the user experience.
Original PR description
Steps to reproduce: ==== - Place an order through Urbanpiper. - Edit the order and remove the customer. - Open the ticket screen and click the info button. - A traceback occurs. Cause: ==== - Customer details were rendered even when no customer was linked to the order. Fix: ==== - Display customer details only when a customer is present on the order. task-6233812 Forward-Port-Of: odoo/enterprise#120290 Forward-Port-Of: odoo/enterprise#118147
This update resolves an issue where expense descriptions weren't automatically translated when using different database languages (like French). The fix ensures that OCR-extracted descriptions are correctly applied, preventing the expense title from remaining stuck on a placeholder. This improves the accuracy of expense data across all Odoo environments.
Original PR description
### Issue On Runbot, trial, and client databases, the automatic extraction of the description does not work when a user changes the database language When an expense is first generated up to 19.0, it…
### Issue
On Runbot, trial, and client databases, the automatic extraction of the description does not work when a user changes the database language
When an expense is first generated up to 19.0, it requires a name and is temporarily given a localized placeholder like "Dépense sans titre..." in French
When the OCR results arrive, the system is supposed to detect this generic fallback string and overwrite it with the real extracted description
However, because of a language mismatch, the system fails to recognize its own placeholder. It incorrectly assumes the user manually entered that text and, to prevent losing user data, refuses to replace it
Before the fix, the title remains stuck on the placeholder
In very rare cases, the translation applies correctly, but it fails most of the time
### Cause
The OCR successfully finds the correct description, but in `_fill_document_with_results`, the expense name is not replaced
This seems to happen because `self` in `self._get_untitled_expense_name("")` carries a residual context that could override the correct language to use during the automated extraction process
Even though the user record and the detected language are correctly set to the alternative language, `default_receipt_name` appears to be generated in English ("Untitled Expense")
This would cause the subsequent string comparison with the actual translated name stored in the database to fail, blocking the update
### Fix
I made some tests in some generated RunBot and the user is correct and also the associated lang
I supposed self was containing lang details overriding the correct language to use
`self.env['hr.expense'].with_context(lang=user_id.lang)` seems to be working
### Steps to reproduce
The issue cannot be reproduced locally, follow these steps on a Runbot instance:
- Retrieve IAP OCR credentials from a trial database
- Enable Developer Mode in Settings
- Go to Settings -> Technical -> IAP -> IAP Accounts
- Add the credentials for the Document Digitization service
- Go to the Expenses app
- Change the user's language to French
- Import the expense image from the ticket
- Open the newly created Expense and click Refresh
Before the fix, the title should stay `Dépense sans titre...` If it's not the case, try a second import, it works times to times
opw-6103935
Forward-Port-Of: odoo/enterprise#118661This update fixes an issue where the reconciliation reporting dialog was not displaying draft journal items, leading to an inaccurate count. By removing a default filter, the dialog now shows all matching items, providing a more complete and reliable reconciliation view. This improves the accuracy of financial reporting.
Original PR description
The reconcile badge counts draft and posted journal items, but the matching dialog forces a posted filter by default, this makes the dialog show fewer lines than count as it discards the draft ones. Remove the default posted search filter so the dialog displays all matching items. task-6234801
This update refactors the bank statement import controller to avoid conflicts with other Odoo modules. By using a more generic controller and removing unnecessary code, the import process is now more reliable and efficient. This change ensures consistent behavior and reduces potential errors.
Original PR description
account_bank_statement_import_view was using the same controller used in account.move which caused some wrong behavior when some logic isn't shared between both modules, now account_bank_statement_import uses a generic controller that doesn't add unneeded behavior. As well as removing all of the account move classes from bank statement import and using generic ones or ones specific to account bank statement import. task-5892419