Daily updates from Odoo
Thursday, January 22, 2026
21 changes · saas-18.3
Resolved issues and error corrections
This update fixes a bug that caused Odoo to crash when creating invoices in USD with zero amounts and tax/discount applied. The fix prevents a division-by-zero error during currency conversion, ensuring invoices can be generated correctly. This improves stability and prevents data loss.
Original PR description
**Steps to reproduce:** 1. Install the `l10n_it_edi` and switch to IT company 2. Go to Accounting → Invoice. 3. Create an invoice add partner and change the currency to USD 4. Add a product and apply tax and discount of 100% and confirm 3. Click on Send **Issue:** A ZeroDivisionError is raised during the Italian EDI XML generation. `ZeroDivisionError: float division by zero` **Cause:** The conversion rate is computed by dividing `amount_total` by `amount_total_signed` without handling the case where `amount_total_signed` is `0.0`. **Solution:** Skip the conversion rate computation when the signed total amount is zero, preventing the division by zero **opw-5481821** Forward-Port-Of: odoo/odoo#244423
This update resolves an error that occurred when generating PDF reports for accounting, specifically when a contact didn't have a name assigned. The fix ensures that the report can now be successfully exported even with contacts lacking a name, improving report generation reliability.
Original PR description
Currently, an error occurs when exporting an accounting report to PDF if any of the selected contacts do not have a name. **Steps to reproduce:** - Install the `account_reports` and `contacts`…
Currently, an error occurs when exporting an accounting report to PDF if any of the selected contacts do not have a name. **Steps to reproduce:** - Install the `account_reports` and `contacts` modules. - Go to Contacts and open any contact (e.g., Azure Interior). - Click `Add` > `Save & Close`, then `save` the contact. - Navigate to Accounting > Reporting > Aged Receivable. - Click `Partners` button and select the newly created contact (e.g., `Azure Interior, Other Address`). - Click `PDF` to export the report. **Error:** `TypeError: sequence item 0: expected str instance, bool found` **Root Cause:** At [1], `options['selected_partner_ids']` is built using `partner.name`, which may be `False` for unnamed contacts. At [2], the `partner_value` list may therefore contain `False` entries coming from `options['selected_partner_ids']`. When calling `', '.join(partner_value)`, an error is raised because the list contains `non-string` (`bool`) values. **Fix:** This commit prevents errors when exporting reports to PDF and ensures that partner names are displayed in the report the same way as in the partner selection widget. [1]: https://github.com/odoo/enterprise/blob/a0ec2fcdc043cf52f1a646e84b9b97466072d47f/account_reports/models/account_report.py#L745 [2]: https://github.com/odoo/enterprise/blob/099c7b94ad08f83873c05ec528e16fbf806f47f2/account_reports/data/pdf_export_templates.xml#L84-L93 opw-5467321 Forward-Port-Of: odoo/enterprise#105025 Forward-Port-Of: odoo/enterprise#103828
This update corrects a typographical error in the tests for the search highlight feature within Odoo. The fix ensures the tests run correctly and prevents potential issues with search functionality. This is a routine maintenance update.
Original PR description
Intoduced by https://github.com/odoo/odoo/pull/118794 Forward-Port-Of: odoo/odoo#244832 Forward-Port-Of: odoo/odoo#244720
This update resolves a problem where FedEx labels incorrectly displayed addresses containing special characters (like accented letters). The code has been updated to ensure all addresses are converted to ASCII characters before being sent to FedEx, preventing display issues and ensuring accurate label formatting. This improves the reliability of shipping labels.
Original PR description
Issue ----- Fedex does not handle special characters in addresses, so passing an address such as "Rue de Libération 15" will show as "Rue de Lib...ration 15" on labels. ----- Ticket: opw-5419724 Forward-Port-Of: odoo/enterprise#104979 Forward-Port-Of: odoo/enterprise#104265
This update resolves an issue where invoices sent to Peppol were failing validation due to an incorrect UN/ECE code. The fix removes a specific UNECE code ('HD') that wasn't accepted by Peppol, ensuring invoices now pass validation and can be successfully transmitted.
Original PR description
**Steps to reproduce:** - Use a Belgian company - Create a Belgian contact with "EU Standard (Peppol Bis 3.0)" as eInvoice format - Create an invoice for that customer with a product using "Pack of 6" as unit of measure - Confirm the invoice - Send it to Peppol **Issue:** The validation of the invoice fails with the following error: "[BR-CL-23]-Unit code MUST be coded according to the UN/ECE Recommendation 20 with Rec 21 extension" **Cause:** The UNECE code used for "Pack of 6" UoM is "HD". "HD" is a correct UNECE code for "Half Dozen". However, it is not part of the subset of codes accepted by Peppol. opw-5463212 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244668
This update resolves an issue where iOS users were unable to save custom star ratings for product reviews. The problem stemmed from a technical glitch that reset the rating to the default 4 stars before submission. This fix ensures that iOS users can accurately submit their product ratings, improving the overall customer experience.
Original PR description
## Versions
18.0+
## Issue
On iOS devices, when submitting a product review with a custom star rating, the selected value would revert to the default (4 stars) before submission.
## Steps to reproduce
*On a laptop*
- Open Editor mode on a product eCommerce page:
- Select any product element (e.g. click on the price);
- Activate customer ratings and save.
*On a physical Apple mobile device (iPhone or iPad) or on an iOS emulator via XCode (only on MacOS)*
- Go to the product's eCommerce page:
- Move down to the "Customer Reviews" section and un-toggle it:
- Write down a review;
- Click on any star rating but 4;
- Send.
## Cause
`mouseleave` event is triggered before the rating is saved and resets the rating to the default 4-star one.
## Solution
Only trigger `mouseleave` event on devices handling them correctly and post the number of visible stars on the form.
opw-5142682
Forward-Port-Of: odoo/odoo#234308This update resolves a visual glitch on mobile websites (particularly with RTL languages) where a horizontal scrollbar briefly appeared when the header reappeared after scrolling. The fix ensures the header's styling is correctly synchronized, preventing this momentary disruption of the user interface. This improves the overall mobile experience and consistency.
Original PR description
There was an horizontal scrollbar that would appear for a short time after scrolling back to the top of the page. This would occur because the header would still have the "transform" property but the class "o_header_affixed" was already removed. To fix the issue, the header transform is now applied using dynamicContent, to synchronize the style and class correctly. This requires the standard header to have "transition: none" applied after it is scrolled since "translate(0, -100%)" would trigger an animation when hiding the header. task-5155878 Forward-Port-Of: odoo/odoo#241980
This update corrects a bug in the Master Production Schedule (MPS) that caused excessive component reordering for kit products. Specifically, the system was incorrectly calculating the quantity of components needed, leading to inflated order quantities. This fix ensures accurate replenishment and prevents over-ordering of components.
Original PR description
***Behavior:*** In a setting with a second warehouse that is supplied by the first one. Creating a product that uses that ressuply route, and then adding it to the bom of a kit product will make it…
***Behavior:*** In a setting with a second warehouse that is supplied by the first one. Creating a product that uses that ressuply route, and then adding it to the bom of a kit product will make it so that when ordering the kit product to the second warehouse from the MPS, the system will create an order for an exponential amount of components. When calling action_replenish, kit products for which the components don't have an MPS entry will have their product_ratio computed to know how many components to reorder. However the current formula is wrong or outdated and ends up returning the squared amount. ***Steps to reproduce:*** - Create a second warehouse. - Check Resuply From 'First Warehouse' (this will unarchive a route) - Create a product that uses that route for reordering. - Create a second product - Create a kit for that product BOM composed of the first product make sure the amount of component is more than 1 - In the Master Production Schedule: Add the kit product and make sure it is produced in the second warehouse with the unarchived route. - Add any amount to reorder in 'Replenishment' then click the Order button. - If you go to deliveries and look for your component, you'll see the amount of component per kit squared multiplied by the reordered kit amount. opw-5351460 Forward-Port-Of: odoo/enterprise#101462
This update corrects a technical issue where a function was incorrectly called in the payroll module. The fix creates a new function in the documents module that properly calls the correct function, ensuring the payroll process runs smoothly. This resolves a potential error and maintains the stability of the HR and payroll features.
Original PR description
Issue: `_check_create_documents` is called in 'hr_payroll' but only defined in 'documents_hr_payroll' Solution: Create a new method that will be redefined in 'documents_hr_payroll' to call `_check_create_documents` opw-5213979 Forward-Port-Of: odoo/enterprise#104282
This update resolves an issue where invoices couldn't be processed correctly when multiple payment methods shared the same code. The fix ensures payment method codes are read-only, preventing conflicts and maintaining compliance with Mexican regulations. It also includes safeguards to handle existing data inconsistencies.
Original PR description
Currently, an error occurs when a user tries to post an invoice using a payment method that shares the same code as another payment method. Steps to replicate: - Install `l10n_mx_edi` and…
Currently, an error occurs when a user tries to post an invoice using a payment method that shares the same code as another payment method.
Steps to replicate:
- Install `l10n_mx_edi` and `accountant` with demo and switch to `ZAPATERIA URTADO ÑERI` (Mexican company).
- Go to `Accounting > Configuration > Payment Way Codes (MX)`.
- Open `Efectivo` and change its code to `02`.
- Create a new Invoice, select `Efectivo` in the Payment Way.
- Add a customer and a move line, then confirm the invoice and send it (make sure CFDI is checked).
Error:
```
File '/home/odoo/src/enterprise/19.0/l10n_mx_edi/models/account_move.py', line 424, in _l10n_mx_edi_get_extra_invoice_report_values
cfdi_infos['payment_way'] = f'{payment_way} - {payment_method.name}'
File '/home/odoo/src/odoo/19.0/odoo/orm/fields.py', line 1659, in __get__
record.ensure_one()
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_mx_edi.payment.method(1, 22)
```
Cause:
- Issue originated through this [PR] that gave access to write on the model.
- As the user made the codes of two payment methods same, the [search] returned two records and while accessing `payment_method.name` on two records it results into this error.
Solution:
- Made the fields read-only via XML to prevent users from changing the payment method codes established by the Mexican government.
- Added limit to the search query to prevent multiple records. (for existing DBs that might have changed payment method codes).
- Removed unlink rights on the `l10n_mx_edi.payment.method` model.
- Added a SQL constraint to allow only unique values for the code.
[PR]: https://github.com/odoo/enterprise/pull/38046
[search]: https://github.com/odoo/enterprise/blob/18117c6a9fbf270ace1c551616828a85713d5225/l10n_mx_edi/models/account_move.py#L423
sentry-7171030995
Forward-Port-Of: odoo/enterprise#104914
Forward-Port-Of: odoo/enterprise#103944This update resolves an issue where non-administrator editors couldn't save images from Unsplash. The fix ensures that users with editor permissions can successfully upload and save these images, improving website customization capabilities. It addresses a security concern related to user access rights.
Original PR description
Scenario: - Setup Unsplash and install website - Set a user as "Website: Editor and Designer" - Login as that user and go to any website page with a qweb view - Go to edit mode and drop Text-Image in…
Scenario: - Setup Unsplash and install website - Set a user as "Website: Editor and Designer" - Login as that user and go to any website page with a qweb view - Go to edit mode and drop Text-Image in a view - Replace the image with an unsplash image and then save Result: the save fails without any message shown, and there is a security access WARNING in the logs. Note: a similar scenario can be done for a restricted editor that is editing a HTML field it has write access to. Issue: to save a model with res_id 0, we need to either be admin (base.group_system) or the record creator. Since 9c9c58a5a10101532cbf046d21d4a63c2b7d2838 to bypass the mimetype neutering of happening, we create the attachment as SUPERUSER. Then when we modify the attachment url (for unsplash images), we have no access right to the attachment since we are not the creator. Fix: create the attachment with the current user, and only use SUPERUSER to set the mimetype if it was neutered (ie. the user doesn't have write access right to ir.ui.view, which in normal use case should only happen for "Restricted Editor"). This way the image is created by the user that uploaded it and not SUPERUSER. opw-4850611 opw-5387258 opw-5489219 Forward-Port-Of: odoo/odoo#244831 Forward-Port-Of: odoo/odoo#219472
A test related to user signup was failing intermittently due to an issue with the URL being generated. This update corrects the test to handle both absolute and relative URLs, ensuring consistent test results and improved stability of the signup process. This resolves a technical issue that could have impacted user onboarding.
Original PR description
Bug === On some runs, the redirect URL is absolute and not relative, (eg: `http://127.0.0.1:8069/web/signup?db=...`) and so the test needs to be adapted. Task-5857520 Forward-Port-Of: odoo/enterprise#105027
This update prevents errors when users attempt to upload corrupted or encrypted PDF files when creating quotation document headers and footers. Previously, these files would cause a system error. This change ensures a smoother user experience by gracefully handling invalid PDF uploads, allowing users to continue generating quotes without interruption.
Original PR description
Currently, an error occurs when uploading `encrypted or incomplete` PDF files (missing EOF marker) while creating a quotation document header or footer. **Steps to reproduce:** - Install the…
Currently, an error occurs when uploading `encrypted or incomplete` PDF files (missing EOF marker) while creating a quotation document header or footer. **Steps to reproduce:** - Install the `sale_pdf_quote_builder` module. - Navigate to: Sales > Configuration > Headers/Footers. - Upload encrypted file [1], or incomplete file [2]. **Error:** `PyPDF2.errors.DependencyError: PyCryptodome is required for AES algorithm` `PyPDF2.errors.PdfReadError: EOF marker not found` **Root cause:** At [3], `_get_form_fields_from_pdf` and `_ensure_document_not_encrypted` directly call `pdf.PdfFileReader`, when it fails to read or decrypt the file, Python raises an error. **Fix:** This commit prevents errors when users upload unreadable or encrypted PDF files. [1]: https://drive.google.com/file/d/1moSlwXHkqcV6_7zHBNhLMLi-9Ye_xDGJ/view?usp=sharing [2]: https://drive.google.com/file/d/16O4LLH8dL0RWmbOx4HrcooFUyesWaVi-/view?usp=sharing [3]: https://github.com/odoo/odoo/blob/694f1d0fb03b56dd41a59eb676e56622634cc91b/addons/sale_pdf_quote_builder/utils.py#L11 sentry-6928220164 opw-5227601 Forward-Port-Of: odoo/odoo#245109 Forward-Port-Of: odoo/odoo#230712
This update ensures the chatbot answer dropdown only displays relevant answers for the current chatbot script, regardless of user input. Previously, an issue caused all chatbot answers to be shown, even those from other scripts. This fix resolves a bug introduced after a recent code change, improving the user experience and data accuracy.
Original PR description
**Description of the issue/feature this PR addresses:** In the `triggering_answer_ids` searchable dropdown, when no value is entered, the `_search_display_name` method of `chatbot_script_answer` is…
**Description of the issue/feature this PR addresses:**
In the `triggering_answer_ids` searchable dropdown, when no value is entered, the `_search_display_name` method of `chatbot_script_answer` is not called. Instead, the ORM falls back to the field’s default domain and returns all `chatbot.script.answer` records, including those from other scripts. When a value is entered, `_search_display_name` is triggered and the results are filtered correctly.
This behavior changed after PR #201587, where the `operator_optimization` step started executing before `determine_domain`. Since `determine_domain` is the step that triggers `_search_display_name`, it no longer gets called when the domain `('name', 'ilike', '')` is stripped by `operator_optimization`. Therefore, filtering only works when a non-empty filter value is provided.
**Current behavior before PR:**
All `chatbot.script.answer` records are shown in the `triggering_answer_ids` dropdown when no search value is entered, even if they don’t belong to the current chatbot script.
**Desired behavior after PR is merged:**
The `triggering_answer_ids` dropdown only shows answers belonging to the current chatbot script, regardless of whether a search value is entered.
task-[4968490](https://www.odoo.com/odoo/project/1519/tasks/4968490)This update resolves an issue where the 'Pending' button in the manufacturing order process incorrectly stopped productivity records for all employees involved, instead of just the current one. The fix ensures that only the productivity record associated with the currently logged-in employee is stopped when the 'Pending' button is clicked, improving workflow efficiency.
Original PR description
Steps to reproduce the bug:
- Create a storable product P1 with the following BoM:
- Create a new operation OP1
- Create a manufacturing order to produce one unit of P1
- Confirm the manufacturing order
- Log in as Mitchel (admin) and start OP1
- Log in as Marc (demo) and also start OP1
- Click on Pending
Problem:
Both “mrp.workcenter.productivity” records are stopped, instead of stopping only the one linked to
The `button_pending` method was stopping productivity records for all employees linked to the work order.
opw-5453752
Forward-Port-Of: odoo/enterprise#103853
Forward-Port-Of: odoo/enterprise#103553This update fixes a bug where invalid formatting in module descriptions (like Markdown) could cause Odoo to crash. The fix allows for a fallback to raw text rendering, ensuring stability and preventing server interruptions during module installation or updates. This improves the overall reliability of the Odoo platform.
Original PR description
Modules containing valid Markdown in their description or README.md could cause Odoo to crash during startup or module updates if the content confused the reStructuredText (RST) parser. ### Steps to…
Modules containing valid Markdown in their description or README.md could cause Odoo to crash during startup or module updates if the content confused the reStructuredText (RST) parser.
### Steps to reproduce
1. Create a module with a manifest like this:
```py
{
'name': 'base',
'description': """
....
""",
}
```
2. Start the Odoo server or attempt to install or update update the module.
3. The server crashes:
```
docutils.utils.SystemMessage: (SEVERE/4) Unexpected section title or transition.
```
### Cause
The crash occurs during the execution of the `_get_desc` method in the `ir.module.module` model, which computes the `description_html` field.
When Odoo processes a module, it checks for a pre-rendered HTML description at `static/description/index.html`. If this file is missing, the `_get_desc` method attempts to generate HTML from the module's `description` field (often populated from the `README.md` file) by calling the `docutils.core.publish_string` function.
The **docutils** library is designed specifically for **reStructuredText (RST)**. If the input text contains structural patterns that violate RST rules—such as inconsistent header levels or "transitions" in invalid contexts—docutils flags a severe error and raises a `docutils.utils.SystemMessage` exception.
### Fix
This commit handles these exceptions and falls back to a raw text rendering. It also improves the logic by removing the restriction that prevented non-application modules from rendering their description via RST.
opw-5424131
Forward-Port-Of: odoo/odoo#243517This update addresses a correction in how Swiss payroll tax rates are reported to the tax authorities. Specifically, it adapts the import process to account for changes related to single canton reporting for 2026, ensuring accurate tax calculations and compliance with Swiss regulations. This ensures accurate reporting for Swiss businesses using the Enterprise module.
Original PR description
Forward-Port-Of: odoo/enterprise#104333
This update corrects a bug where the Gantt progress bar displayed an incorrect estimated duration for work orders after changing the assigned workcenter. The issue stemmed from how the system calculated the finished date, leading to inaccurate progress visualization. This ensures the Gantt chart accurately reflects the expected completion time.
Original PR description
**Issue** Changing the workcenter of a workorder to another with a different time efficiency does not correctly update `date_finished`, causing the Gantt progress bar to show an incorrect expected…
**Issue** Changing the workcenter of a workorder to another with a different time efficiency does not correctly update `date_finished`, causing the Gantt progress bar to show an incorrect expected duration. **Steps to reproduce** 1. Create two workcenters marked as alternatives (100% and 50% efficiency). 2. Create a BOM operation that produces 100 products with a 1h expected duration each, on the 100% workcenter. 3. Create and plan an MO using this BOM. 4. In Planning > Planning by Workcenter (Gantt), drag the workorder to the 50% efficiency workcenter. → Expected duration remains 100h instead of 200h. 5. Drag the same workorder back to the 100% workcenter. → Expected duration becomes 200h instead of 100h. **Cause** `date_finished` is recomputed in `write()` using the *previous* workcenter’s efficiency, because the duration calculation happens before the new `workcenter_id` is applied: https://github.com/odoo/odoo/blob/18.0/addons/mrp/models/mrp_workorder.py#L471 Since the Gantt progress bar uses the interval [`[date_start, date_finished]`](https://github.com/odoo/enterprise/blob/18.0/mrp_workorder/models/mrp_workorder.py#L672C13-L674C107) to compute the expected duration (via `_web_gantt_progress_bar_workcenter_id`), the displayed duration becomes wrong. opw-5224272 Forward-Port-Of: odoo/odoo#245002 Forward-Port-Of: odoo/odoo#239021
This update fixes an issue where PDF quotes weren't correctly identifying form fields when dealing with products organized in a hierarchy. Now, the system accurately recognizes and incorporates form fields within these complex product structures, ensuring accurate quote generation for businesses with multi-level product offerings. This enhancement improves the reliability and completeness of our sales documentation.
Original PR description
- For Hierarchy objects, we have to check '/T' in '/Parent' instead directly within '/Annot' like flat fields. Desired behavior after PR is merged: - Support form fields with Hierarchy objects. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#238323
This update fixes an issue where refund and bill payments for the same bank and partner weren't always combined into a single payment. The change ensures that outbound (bills) and inbound (refunds) payments to the same bank and partner are automatically consolidated, reducing the number of payments created and simplifying accounting processes. This improves efficiency and accuracy.
Original PR description
When we register payments for a list of journal entries, the `account.payment.register` wizard computes batches and sometimes merge them together. For instance, this allows to create a single payment if there is an outbound (a bill to pay) and an inbound (a refund to receive) payment to the same bank for the same partner. Instead of creating two payments of -1000 and +500, we only create one of -500. Currently, this mechanism does not always work. That's because the `batch_key` used to decide whether to merge or not refers to a value that is not updated in the loop. Related ticket: opw-5401372 Forward-Port-Of: odoo/odoo#242863
This update resolves an issue where tax reverse charges weren't correctly reported on BIS3 invoices. The system now accurately handles these charges by classifying them as 'Prepaid Amounts,' ensuring accurate tax calculations and compliance. This change improves the reliability of financial data generated from these invoices.
Original PR description
There is no WithholdingTaxTotal node in BIS3. You cannot report any negative tax amount as taxes. You can only report VAT taxes but tax reverse charge are not considered as VAT. This commit reports the tax reverse charge amount as a PrepaidAmount instead. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#240525