Thursday, January 29, 2026
29 changes · saas-19.1
New functionality added to Odoo
This update adds the necessary data to support Taiwan's VAT tax reporting requirements within Odoo. Specifically, it incorporates data records for the `account.return.type` model, ensuring compliance with local regulations. This enhancement improves the functionality of the Taiwan localization module.
Original PR description
This commit adds the necessary data records for the `account.return.type` model to support Taiwan VAT tax return. [Task-3371895](https://www.odoo.com/odoo/project.task/3371895) Forward-Port-Of: odoo/enterprise#104698
Enhancements to existing features
This update expands Odoo's language support to include Spanish, recognizing the significant number of Spanish speakers. By adding Spanish translations, we improve the usability of Odoo for a wider range of customers and users. This enhancement aligns with our commitment to global accessibility.
Original PR description
The official language is English, but Spanish is spoken by ~41 million. task-5247124 Forward-Port-Of: odoo/odoo#245702 Forward-Port-Of: odoo/odoo#245358
Resolved issues and error corrections
This update removes the 'New' button from the DIMONA Declaration List view in the l10n_be_hr_payroll module. This change simplifies the user interface and corrects a minor usability issue, ensuring a cleaner and more straightforward process for generating DIMONA declarations.
Original PR description
. Remove the New button on DIMONA Declaration List view task-5471873
Code cleanup and technical improvements
This update enhances the testing process for Odoo's Arabic accounting modules (l10n_ar). Specifically, a new testing method and refactoring of the test suite ensures more reliable and accurate verification of these modules, improving overall system stability and accuracy for Arabic-speaking users.
Original PR description
- Implemented a working `assert_json` method on `AccountTestInvoicingCommon`, that also supports the ignore_schema system and quick save using the `SAVE_JSON` test tag. - Refactors the whole test suite of `l10n_ar*` modules to use the new accounting test helpers properly. task-4891206 Forward-Port-Of: odoo/odoo#245457 Forward-Port-Of: odoo/odoo#242309
This update expands Odoo's language capabilities to include Spanish, recognizing the significant Spanish-speaking population. This enhancement improves usability for a wider range of customers and aligns with global market needs. It's an important step in supporting diverse user bases.
Original PR description
The official language is English, but Spanish is spoken by ~41 million. task-5247124 Forward-Port-Of: odoo/enterprise#105494 Forward-Port-Of: odoo/enterprise#105246
This update aligns the appointment quick create form with recent design changes for calendar dialogs, ensuring a consistent user experience. The changes restore proper icon and field alignment, improving the visual appearance and usability of the appointment scheduling feature. This addresses a design oversight identified in odoo/odoo#238855.
Original PR description
Following odoo/odoo#238855 the dialogs design have been improved. While improving the calendar dialog, the appointment one has been overlooked. Adapting the appointment quick create form following the changes in its parent calendar form view. Restoring icons and fields alignment. Task-5887839
This update increases the width of barcodes on customer receipts generated by the Point of Sale (POS) loyalty program. Previously, the barcodes were too narrow, making them difficult for staff and customers to scan accurately. This change ensures seamless order processing and improved customer experience.
Original PR description
Step to reproduce; - install pos_loyalty - create a loyalty program of type "next order coupon" with minimum spend of 1$. - open pos and settle a order, see receipt. Issue: - currently bar-code is too narrow, making it difficult for to be scanned Fix: - increase the width of barcode, so it can be easily scanned. <table> <tr> <td> <b>Before</b> </td> <td> <b>After</b> </td> </tr> <tr> <td> <img width="451" height="508" alt="image" src="https://github.com/user-attachments/assets/a0d1e95e-0a9d-4552-977a-0ad9686867b8" /> </td> <td> <img width="456" height="517" alt="image" src="https://github.com/user-attachments/assets/40d04ac4-9ffc-4f81-a063-31b3ea26b4e1" /> </td> </tr> </table> opw-5363916 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244353 Forward-Port-Of: odoo/odoo#242469
A bug preventing users from duplicating skills in the HR module has been fixed. This update ensures that users can now successfully create copies of existing skill entries without encountering validation errors. This improves the usability of the skills management feature.
Original PR description
Version: - saas-18.2 Steps to reproduce: - Install the hr_skills module - Go to the Skills menu - Select a skill and click Duplicate Issue: - A validation error appears when duplicating a skill Solution: - Updated the copy_data method so skills can be duplicated without causing a validation error Task - 5481185 Forward-Port-Of: odoo/odoo#243227
A test within the sale_pdf_quote_builder module was failing due to how it handled PDF files. This update replaces the test's invalid PDF data with a real, encrypted PDF, resolving the warning messages and ensuring the test now passes. This improves the stability of the Nightly builds.
Original PR description
The `test_wrong_pdf` test fails on runbot in the `Nightly build` when executed under `Distro Builds > Testing distro PureTrixie without requirements for config Parallel testing`. **Steps to…
The `test_wrong_pdf` test fails on runbot in the `Nightly build` when executed under `Distro Builds > Testing distro PureTrixie without requirements for config Parallel testing`. **Steps to reproduce:** - Install `sale_pdf_quote_builder` module. - Run `test_wrong_pdf` (Make sure `PyPDF==5.4.0` is installed). - Observe `PyPDF` warnings in the logs. **Warnings:** ``` WARNING server pypdf._reader:435 invalid pdf header: b'test' WARNING server pypdf._reader:435 EOF marker not found WARNING server pypdf._reader:435 EOF marker not found ``` **Root cause:** Odoo officially supports the PyPDF version defined in requirements.txt [1]. The test passes with `PyPDF2`, but `PyPDF` is stricter and emits warnings when parsing arbitrary byte content. Because the test uses raw bytes instead of a structurally valid (but unsupported or encrypted) PDF, PyPDF logs warnings. **Fix:** This commit updates the test to use a real encrypted PDF instead of raw bytes, similar to [2]. This commit fixes test failures caused by [3]. **Note:** Refer to [4] for generating the encrypted file. [1]: https://github.com/odoo/odoo/blob/a6af7df429f9cd3bfb60347e9b30cc48fb5bfaff/requirements.txt#L63-L65 [2]: https://github.com/odoo/odoo/blob/0499dbd8944b4002883afab5d3ed76d8e55dab9c/addons/mail/tests/discuss/test_discuss_attachment_controller.py#L63-L75 [3]: https://github.com/odoo/odoo/pull/230712 [4]: https://colab.research.google.com/drive/1UfWSKDluObEkKxCg6eX-nHoe04_FGrEq#scrollTo=A5hO11Eh1qvV runbot-238399 Forward-Port-Of: odoo/odoo#246034
This update fixes a technical error that occurred when a user discarded a configurable product while setting up a Point of Sale order. The issue caused a system error, preventing users from completing transactions. The fix ensures the system handles product discard scenarios correctly, improving PoS functionality.
Original PR description
Steps to reproduce: = - Open a PoS with pos_loyalty - Set a customer - Open a configurable product - Click `Discard` button or press `ESC` key Issue: = - A traceback occurs with the error: `TypeError: Cannot read properties of undefined (reading 'product_id')` Reason: = - When a configurable product is discarded during variant selection, the flow continues and attempts to process an undefined product. Fix: = - Ensure if adding a configurable product is discarded while selecting variant it should not p[roccess futher. task-5481204 Forward-Port-Of: odoo/odoo#243996
This update completes a necessary data upgrade for the Odoo Spreadsheet module. Previously, a client-side data upgrade was missing, which has now been implemented. This ensures data consistency and accuracy within the spreadsheet functionality.
Original PR description
Follow up of 682d6ec1ddb825674999e0db1fc0cc48c3be67c5 where I forgot to add the client-side data upgrade Task-5477426 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244935
This update resolves an issue where the 'Accept & Sign' button remained active even when the customer's name field was empty. The fix ensures the button is disabled when no name is entered, preventing users from accidentally proceeding without a valid signature. This improves the user experience and data integrity.
Original PR description
**Steps to produce:** - Install `sale_management` module. - `Create a SO > Click on Preview > Sign and Pay`. - Remove all text from the Full Name`. **Issue:** - The `Accept & Sign` button remains…
**Steps to produce:** - Install `sale_management` module. - `Create a SO > Click on Preview > Sign and Pay`. - Remove all text from the Full Name`. **Issue:** - The `Accept & Sign` button remains enabled even when the Full Name field is empty. **Root cause:** - At [1], When the `drawCurrentName` method is called, it retrieves text using `getCleanedName`. This method returns an empty string when no name is provided - Despite this, the code still generates an image and passes it to `printImage`, which keeps the button enabled. **Solution:** - If the cleaned name is empty or contains only spaces, do not generate image. - Instead, immediately clear the signature pad so the button remains disabled. [1]https://github.com/odoo/odoo/blob/9dedf75810bd6b7a92fe5bd279bf6bae98834750/addons/web/static/src/core/signature/name_and_signature.js#L103-L109 **Before:** <img width="400" height="400" alt="before" src="https://github.com/user-attachments/assets/5ebdf852-4cba-4e1d-9ae4-7373e4b8b91d" /> **After:** <img width="400" height="400" alt="after" src="https://github.com/user-attachments/assets/9280aa66-4f22-40d6-8a22-326cec24378d" /> **opw-5361890** --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#238638
This update allows users to directly edit the background color of snippets within the s_tabs website builder. Previously, users had to work around this limitation by setting background images/videos. This change also resolves an issue where default background colors couldn't be removed, creating a more intuitive editing experience.
Original PR description
Before this commit, it was not possible to edit the background color of a snippet dropped within the s_tabs snippet. The user could set the background image / video, but not the color. The user could work around the limitation by setting the background color of a snippet, saving it, then dropping it within the s_tabs snippet. Therefore, it made no sense to disable the background color option. Moreover, adding the background color option fixes the reverse issue: if the user dropped a snippet with a background color set by default, they cannot remove it since the colorpicker was not available. Forward-Port-Of: odoo/odoo#245021
The breadcrumb displayed in the Documents section was incorrectly showing 'Unnamed' when accessed through the systray. This update resolves a technical issue where the system couldn't properly identify the active folder, leading to the incorrect display. Now, the breadcrumb accurately reflects the folder name.
Original PR description
When navigating to Documents through the activity menu (systray), the breadcrumb displays "Unnamed" instead of showing the proper folder name. Steps to reproduce: 1. Click the activity menu icon (clock) in the systray 2. Click on "Documents" in the activity dropdown 3. Observe the breadcrumb shows "Unnamed" The issue occurs because when navigating from the systray, the folder section's activeValueId is undefined. This causes getSelectedFolderAndParents() to call folderSection.values.get(undefined), which returns undefined instead of the default folder. Without a valid folder object, the breadcrumb computation has no context and falls back to displaying "Unnamed". The fix ensures that when activeValueId is undefined, we explicitly pass false to values.get(), which correctly retrieves the root/default folder. opw-5473442 Forward-Port-Of: odoo/enterprise#104297
This update resolves a visual issue where the help section within the employee action view was displaying incorrectly (content overlapping). The fix ensures the help content appears correctly in both the main menu and the action itself. This improves the user experience for employees.
Original PR description
While performing a task I observed an improper view in employees action. Steps to Reproduce : 1. Activate debug mode and go to Employees/Employees/Employees menu 2. Go to its action 3. You will see improper view(content overlapping) in help section. These changes were added [here](https://github.com/odoo/odoo/pull/214810/changes#diff-99eff1b023601f0f844a2fa7efc6c4e62e13a8592d5b799113f848ac4c7565f8L549-R658 ). I have made the changes accordingly so that the Help content looks fine in both Employees menu and action. before : <img width="1695" height="752" alt="image" src="https://github.com/user-attachments/assets/6a847373-5ac2-4877-a07f-ad58338429c5" /> after : <img width="1272" height="823" alt="image" src="https://github.com/user-attachments/assets/16b50843-e736-490a-8a00-44848c6011fa" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244651
This update ensures that refusal emails sent to applicants now use the designated 'Send From' email address specified in the recruitment template. Previously, the emails always used the sender's personal email, leading to inconsistent branding. This change improves the applicant experience and ensures a professional communication.
Original PR description
### Issue: When refusing an application, the system will always use the user's email to send the refusal, even if the template specifies an email to send from. ### Steps to reproduce: - Recruitment > Configuration > Refuse Reasons - Go to one of their template (i.e. "Recruitment: Refuse") - in Settings add a "Send From" email - Recruitment > Applications, click on an application - Click "Refuse" - Select the refuse reason with the template - Refuse - The mail is sent with the user email ### Cause: `_prepare_mail_values()` only returns `self.env.user.email_formatted`. ### Solution: If there is a template with `email_from`, we use this, otherwise `self.env.user.email_formatted` opw-5356662 Forward-Port-Of: odoo/odoo#245937
This update resolves a visual bug where columns in mass emails weren't rendering correctly when sent. The issue stemmed from a conflict between the email's styling and Odoo's CSS, specifically related to color definitions. The fix ensures consistent column alignment in received emails.
Original PR description
**Steps to reproduce:** - Install Mass Mailing and Website apps - Create a new mailing - Add Columns block with different content size - In "Vert. Alignment" field > Select the "Stretch to Equal Height" option - Columns are properly aligned in Odoo - Save the record and send test mail - The columns are not aligned anymore in the received mail **Issue:** Inline styling breaks in mail engines due to `website.scss` file. The `color-mix` css function is used and cast as a `color()` functional notation in the columns `border-color`. The inline styling is then removed by the mail engine (with all siblings attributes) as it is not compatible with this notation. (e.g. `border-color: color(srgb 0.129412 0.145098 0.160784 / 0.15);`) The color normalization step doesn't take this into account as it only checks for rgb patterns. **Fix:** Overwrite the css with the color notation by a default value for mailing. opw-5225248 Forward-Port-Of: odoo/odoo#242649
This update fixes an issue where event registration emails were incorrectly canceling invitations for contacts on a blacklist. The change bypasses the exclusion list process during email sending, ensuring that all registered contacts receive the intended event information. This improves the reliability of event communication.
Original PR description
**Steps to reproduce:** - Install Events & Contacts apps - Open Contacts - Create a contact "BLACKLIST", email: `blacklist@example.com` - Create a contact "GOOD", email: `good@example.com` - Open Settings > Technical > Discuss > Email Blacklist - Create a record with email: `blacklist@example.com` - Open Events - Create an event - Go to the event attendees - Create attendees for both contacts - Open Settings > Technical > Email > Emails - Both email are listed but the blacklisted one is cancelled **Issue:** The composer created in `EventMailScheduler._send_mail` is using `_process_mail_values_state` to find the list of blacklisted records and applies it to filter the mail recipients, which prevents the event mailing from being processed correctly. **Fix:** `use_exclusion_list` is set to `false` on the composer to bypass its exclusion process. opw-5046491 Forward-Port-Of: odoo/odoo#228445
This update fixes an issue where editing a previously edited message could cause incorrect updates due to a mismatch in the message body. The change ensures a reliable comparison of message bodies during editing, preventing data inconsistencies. This improves the overall stability and accuracy of message functionality.
Original PR description
Since #224800, we've been removing the `edited` element from the current message body in order to compare it with the updated body. However, the `edited` element may also be present in the updated body. This change removes the `edited` element from the updated body as well, ensuring a reliable comparison when editing an edited message. Steps to reproduce: - Send a message. - Click `edit`, change the message body and click `save`. - Click `edit` again, don't change the message body this time, then click `save` . - An RPC is made to update the message. Forward-Port-Of: odoo/odoo#245893
This update fixes an issue with the IoT Box's driver download process. Previously, enabling a setting allowed it to download standard drivers, which caused conflicts and duplicated files. Now, the system avoids downloading standard drivers from standard modules to prevent these issues and maintain stability.
Original PR description
The stable IoT Box uses drivers from git repository: it doesn't download them from the database as it used to do. However, sh/on premise clients might want to develop custom drivers that the IoT Box would download. For that, they have to enable a checkbox on the IoT homepage, making the IoT Box download handlers as before. The issue is it will also download standard drivers that are already present on the IoT Box: on newer databases it would simply overwrite them, but on older ones, it would duplicate as names might have changed. Also, it would introduce issues back that were already fixed. To avoid this, we avoid adding drivers from standard modules to the downloaded archive, to prevent issues with the main ones. Forward-Port-Of: odoo/enterprise#105770 Forward-Port-Of: odoo/enterprise#105531
A bug was preventing users with standard access rights from generating serial numbers for tracked products. This was due to a specific write operation within the system's serial number process. This fix ensures that all users can correctly generate serial numbers, improving inventory management functionality.
Original PR description
**Behavior:** Behavior: When logged in as a user with group_user access (member), trying to generate the next few serial numbers for a tracked product from receipts will cause an access error. This…
**Behavior:** Behavior: When logged in as a user with group_user access (member), trying to generate the next few serial numbers for a tracked product from receipts will cause an access error. This happens because there is a write operation on the ir.sequence linked to the serial number at the end of the process that happens only when the 'New' button was previously pressed. And since access rights to ir.sequence are dependant on the base group of the user, changing the user Inventory rights to admin will not resolve the issue. A test has been created to ensure no access error is created when generating sequence numbers as a lower access user, this test would pass without the fix since it is focused on the python function. **Steps to reproduce:** - Create a product that is tracked by serial number - Log in as a user with group_user access (member role) - Go to Inventory -> Operations -> Receipts - Create a new picking and add the product - After clicking on Mark as Todo you'll see Details pop up in the product line - After clicking Details, select Generate Serial/Lots - Click New, then Generate, and you'll get an access error for ir.Sequence opw-5368553 Forward-Port-Of: odoo/odoo#240368
This update corrects a technical issue where order documents weren't being properly updated, leading to potential data inconsistencies. The change forces the update of the document's write date, ensuring accurate tracking and reporting within the l10n_mx_edi module. This resolves a previous limitation in the update process.
Original PR description
Before the commit 8b118a7, the search of the documents to update has been limited and ordered. With the actual domain the records to update will be most of the time the same because is not being updated. To fix this issue we force to update it. OPW-5368047 Forward-Port-Of: odoo/enterprise#104859 Forward-Port-Of: odoo/enterprise#103272
This update corrects a technical issue in the Odoo stock module that prevented accurate filtering of stock orderpoints. Previously, the system wasn't correctly restricting records to the current orderpoint, leading to potential inaccuracies. This fix ensures that stock orderpoints are filtered correctly, improving data reliability.
Original PR description
Description of the issue/feature this PR addresses:
This PR fixes an incorrect domain construction when restricting records to the current recordset.
The existing code attempted to combine domains using expression.AND() but did not apply the result, and referenced an invalid domain field.
Current behavior before PR:
- expression.AND() was called without assigning its return value, so the combined domain was never applied.
- The domain condition used ('ids', 'in', self.ids), which is not a valid searchable field.
- As a result, the intended filtering by the current recordset was silently ignored.
Desired behavior after PR is merged:
- The domain is correctly rebuilt and assigned using expression.AND().
- The filter uses the valid field instead of ids
- Records are properly restricted to the current recordset
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#246156
Forward-Port-Of: odoo/odoo#242799This update fixes an issue where the product quantity and unit of measure fields on the MRP production kanban cards would become unreadable when product names were long. The change ensures these fields remain consistently visible regardless of product name length, improving usability and clarity.
Original PR description
Description of the issue/feature this PR addresses: On MRP production kanban, if the name of the product is too long, `product_qty` and `product_uom_id` fields on the card shrink and become unreadable. This adds proper classes to keep those fields from shrinking no matter how long product's name is. Current behavior before PR: <img width="1561" height="303" alt="image" src="https://github.com/user-attachments/assets/08e299be-c6e2-4241-b289-aaa2fab9a94f" /> Desired behavior after PR is merged: - The size of the product's name should be fine no matter how long the name of the product is. - The `product_qty` and `product_uom_id` should not shrink if the name of the product is long. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#245861
This update resolves a minor technical issue within the l10n_jo_hr_payroll module. A typographical error in the module's manifest file has been corrected. This ensures the module functions correctly and integrates smoothly with the Odoo system.
Original PR description
Fix some typos in the manifest of the module. Task: 5462506
This update resolves an issue where Odoo couldn't connect to printers with overly long device names. The fix automatically shortens these names to comply with CUPS's 127-character limit, ensuring reliable printer connectivity. This prevents connection failures and improves the overall printing experience.
Original PR description
CUPS has a limit on printer names of 127 characters, which means that if a device has a very long device URI, it can exceed this limit and cause an error when we try to add it to CUPS:
```
Failed to add printer 'dnssdPhotosmart%207520%20series%20%40%20Guillaume%E2%80%99s%20MacBook%20Air%20(2)_ipp_tcplocalcups?96d0de60-096c-3d08-5e2d-893393e10c2b'
Traceback (most recent call last):
File "/home/pi/odoo/addons/iot_drivers/iot_handlers/interfaces/printer_interface_L.py", line 242, in set_up_printer_in_cups
self.conn.addPrinter(name=device['identifier'], device=device['url'], **ppdname_argument)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
cups.IPPError: (1024, 'client-error-bad-request')
```
We fix this error by truncating the identifier to 127 characters maximum.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#246151
Forward-Port-Of: odoo/odoo#245910This update optimizes how Odoo builds SQL queries when joining related models with delegated access. Previously, joining on fields with delegated access required extra permissions, which is now bypassed. This change improves query performance and ensures consistent access control, particularly when using search functionality.
Original PR description
When building the SQL for a related field, we join the table for the comodel and may apply user access to that comodel. Using *inherits* already adds record rules for that field, so joining on the field on which "delegates" access to fields, can be done without additional permissions.
```py
class M1(Model): ...
class M2(Model):
_inherits = {'m1': 'm1_id'}
m1_id = fields.Many2one(...)
```
Consider the following, `Query(m2_record).m1_id` should join without additional access rules. This is fine because the query usually comes from a `_search` (which has added the necessary permissions).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update fixes an issue where optional products for a sale order were always added at the end of the order, regardless of where the main product was placed. The change ensures that optional products are now correctly inserted immediately after their corresponding main product line, creating a cleaner and more organized sale order view. This improves the user experience and data clarity.
Original PR description
# Steps to reproduce: * Create a sale order with two sections * In the first section, use the ellipsis to add a product that has optional products configured and add its optional products * The optional product lines are added under the next section instead of the current one # Issue: * Optional products are always appended at the end of the order, even when the main product is inserted in the middle # Cause: * While creating new lines in `sale_product_field.js`, the intended insertion position is ignored # Solution: * Update the configurator save logic to insert optional product lines immediately after their corresponding main product line Affected Version-19.0 opw-5445800 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243069
This update streamlines the testing process for the Ar-EDI module by automatically verifying data against JSON files. This change allows tests to run without external dependencies and simplifies updates to test data through a simple tag.
Original PR description
This commit refactors the whole `l10n_ar_edi` test suite to use the new helpers, and made it possible for the test to (finally) be run without external mode. Now, when running these new tests, the test framework will by default assert the request data with their associated JSON file. When a change is made, new overwrites for the test files can be easily changed by just adding the `SAVE_JSON` test tag on the command to run the tests. task-4891206 Forward-Port-Of: odoo/enterprise#105299 Forward-Port-Of: odoo/enterprise#103370