Thursday, February 5, 2026
29 changes · saas-19.1
Resolved issues and error corrections
A performance issue impacting the Odoo.com website forum search has been resolved. The fix prevents the search from incorrectly indexing forum post content, leading to faster and more reliable search results. This enhancement improves the user experience for forum visitors.
Original PR description
Improve the performance of the website forum search. Issue: There is a significant performance issue with a large number of forum posts impacting odoo.com. This is due to the use of the `<%` operator…
Improve the performance of the website forum search. Issue: There is a significant performance issue with a large number of forum posts impacting odoo.com. This is due to the use of the `<%` operator on the content field of forum posts. It occurs when using the javascript search which autocompletes results in a dropdown on the search bar. To deactivate the search on the `content` column, displayDescription needs to be set to false. but this was not possible due to the data attribute which contains text. setting it to 'false' was still truthy and therefore enabled the fuzzy search in the content column. Fix: - fix a js bug to properly cast the value to a boolean - this was done for other data attributes at the same time. - set the display_description value to false to disable search on the content field. This is aligned with the python post search settings defined in: https://github.com/odoo/odoo/blob/7abd7ba2f38fdb1953c39fd3693f012c2ad1b497/addons/website_forum/controllers/website_forum.py#L95 Forward-Port-Of: odoo/odoo#246581
This update resolves a bug where custom mixins added fields to `res.partner` records caused errors due to incorrect data synchronization. The fix ensures that changes made by mixins are consistently included during the `write()` process, regardless of the order mixins are applied, preventing data inconsistencies.
Original PR description
Description of the issue/feature this PR addresses: When `res.partner` is inherited together with a custom mixin that adds additional values to `vals` inside the `write()` method, the behavior…
Description of the issue/feature this PR addresses:
When `res.partner` is inherited together with a custom mixin that adds additional values to `vals` inside the `write()` method, the behavior depends on the inheritance order. If the mixin is inherited after `res.partner`, the values added by the mixin are not included in the data collected by `res.partner.write()` for later synchronization, which can lead to runtime errors.
Current behavior before PR:
If the inheritance order is:
```python
_inherit = ['res.partner', 'custom.mixin']
```
the custom mixin’s `write()` method is executed after `res.partner.write()`.
As a result, any values added by the mixin are missing from `pre_values_list`, which is built by `res.partner.write()` and later accessed by `_fields_sync()`, causing failures when those fields are expected to be present.
This issue does not occur when the inheritance order is:
```python
_inherit = ['custom.mixin', 'res.partner']
```
because the mixin modifies `vals` before `res.partner.write()` is executed.
Steps to reproduce:
1. Create a mixin model with a new field, then add this field into `vals` inside the `write()` method so it is included in the update flow.
```python
class CustomMixin(models.AbstractModel):
_name = "custom.mixin"
custom_field = fields.Char()
def write(self, vals):
vals['custom_field'] = "foo"
return super().write(vals)
```
2. Inherit the mixin in `res.partner`
```python
class ResPartner(models.Model):
_name = "res.partner"
_inherit = ["res.partner", "custom.mixin"]
```
3. Update a `res.partner` record, an error will be raised
```bash
Traceback (most recent call last):
...
File "/opt/odoo/code/projects/odoo/odoo/orm/fields.py", line 1845, in __set__
records.write({self.name: write_value})
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/odoo/code/projects/odoo/odoo/addons/base/models/res_partner.py", line 907, in write
updated = {fname: fvalue for fname, fvalue in vals.items() if partner[fname] != pre_values[fname]}
~~~~~~~~~~^^^^^^^
KeyError: 'custom_field'
```
Desired behavior after PR is merged:
Values added to vals by a custom mixin during `write()` are consistently available to `res.partner` internal synchronization logic, regardless of the inheritance order.
`res.partner.write()` and `_fields_sync()` should behave correctly even when mixins extend vals and are inherited after `res.partner`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#246927This update prevents users from selecting payment method lines associated with archived journals when managing contacts. Previously, users could inadvertently choose outdated payment methods, leading to configuration issues. Now, archiving a journal automatically removes it from the selectable options, simplifying the process and preventing data duplication.
Original PR description
**Description of the issue/feature this PR addresses:** When selecting a payment method line on a contact, lines related to journals still appear even if the journal has been archived. This can lead…
**Description of the issue/feature this PR addresses:**
When selecting a payment method line on a contact, lines related to journals still appear even if the journal has been archived. This can lead to the accidental use of payment method lines that should no longer be available. There should be no need to delete payment method lines when archiving a journal; doing so causes a loss of configuration if the journal is reactivated later, and leads to data duplication when having to recreate them.
**Current behavior before PR:**
When selecting a payment method line on a contact, lines from archived journals are still visible. Currently, payment method lines must be manually deleted from archived journals to prevent them from appearing in the selection list.
Payment Method Line domain doesn't include `('journal_id.active', '=', True)` domain part.
**Desired behavior after PR is merged:**
Archiving a journal is now sufficient to stop its payment method lines from appearing as selectable options on contacts.
https://www.loom.com/share/05981419c7dd4584b67d27d84e27892a
OPW-5413309 MT-13011 @moduon @rafaelbn @EmilioPascual @Gelojr @yajo please review if you want 😄
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#245947
Forward-Port-Of: odoo/odoo#240369This update fixes an issue where multiple overtime rules were incorrectly adding undertime amounts, leading to inaccurate overtime calculations. The change ensures that only the largest undertime value is considered, providing a more accurate reflection of actual overtime hours. This improves the reliability of overtime reporting.
Original PR description
### Issue:
When having a ruleset with multiple rules, their undertime amounts are added.
### Steps to reproduce:
- Create an overtime ruleset with two rules:
- Based on quantity, worked hours on a Day differs from a specific duration of 8h
- Based on quantity, worked hours on a Day differs from a specific duration of 10h
- Assign this ruleset to an employee
- On a day with no attendance, create one for this employee from 1pm to 6pm
- The computed overtime hours is -8 hours
### Cause:
The undertimes from each rule are added. The first rule computes 3 hours of undertime (8 - 5), the second 5 hours (10 - 5), resulting in 8 hours of undertime.
### Solution:
Instead of adding them, we only keep the greatest undertime.
This ensures that the undertime amount is technically the opposite of the overtime amount.
We only take the undertime value into consideration, whatever the period type of the rule.
opw-5452854
Forward-Port-Of: odoo/odoo#244462This update fixes an issue where the Avco audit report was missing certain stock moves. Previously, the report incorrectly filtered out moves based on company settings. Now, the report accurately includes all relevant stock moves, ensuring more reliable cost reporting for products.
Original PR description
When looking at the Unit Cost History we should ignore moves for standard cost method. Before this fix, we also ignore moves for FIFO or AVCO when the property_cost_method of the product category is not NULL (because is set to a company Y), but it is not set to the current company X. After this fix, we check if the property_cost_method is set to the specific company so that we don't ignore them. OPW-5434503 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244495
This update resolves an issue preventing duplex printing on the Windows IoT device. We've replaced Ghostscript with SumatraPDF, a simpler PDF viewer that natively supports duplex printing. This ensures users can now print PDFs double-sided, improving workflow efficiency.
Original PR description
When printing a PDF using the Windows IoT, first the PDF file is temporarily saved, and then it is printed using Ghostscript which handles parsing the PDF and saving it to the printer. Unfortunately, Ghostscript is unable to print using duplex (double-sided) no matter what settings are provided. To fix this, we replace Ghostscript with [SumatraPDF](https://github.com/sumatrapdfreader/sumatrapdf), which is an open source PDF viewer for Windows, but it is also capable of being used from the command line to print. We simply provide the duplex printing option in the command to SumatraPDF, and it works as expected. [1]: https://github.com/sumatrapdfreader/sumatrapdf task-5149706 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#242307
This update resolves a validation error that occurred when installing modules in companies with branches. The fix ensures the parent company's chart of accounts is loaded first, preventing the creation of duplicate accounts within the branch. This improves module installation stability and functionality.
Original PR description
Issue: Validation Error on installing some modules in companies with branches Step to reproduce: - Create a company in UK - Create a branch to this company - install l10n_uk - install l10n_uk_reports_csi Current behavior: - raise validation error Solution: In AccountChartTemplate, `ref()` function allow searching object from company and parents company. https://github.com/odoo/odoo/blob/468c25b924979f4614705fe43f909af13f83c6a3/addons/account/models/chart_template.py#L1262-L1266 In `_load_data`, it tries to load existing record before creating new account. Loading the parent company first prevent creating a second account in the branch which raise the error. opw-5443912 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a problem where the Open Graph image URL in website configurations was incorrectly set to absolute URLs, causing errors when viewing pages on different domains. The fix ensures that the image URL is relative, preventing this issue and improving website SEO and compatibility with custom domains. This was initially addressed in 19.0 and further refined in this release.
Original PR description
In 17.0 up to master, website_meta_og_img for newly added cover image should be a relative URL instead of an absolute URL since 27th september 2025 commit 4c5d9861e389534f9ca684b9faa1ce6289df5639. In…
In 17.0 up to master, website_meta_og_img for newly added cover image should be a relative URL instead of an absolute URL since 27th september 2025 commit 4c5d9861e389534f9ca684b9faa1ce6289df5639. In combination with: - [1] python fix in 19.0: accept absolute URL in website_meta_og_img - [2] upgrade script in saas-19.1: removes absolute URL that existed in 19.0 when upgrading to saas-19.1 We wanted to removed the error that happened in 19.0 when configuring a cover image (in Optimize SEO) and also using a custom domain These fixes worked up to 19.0, but there is still a possible issue in saas-19.1: - open "Optimize SEO" wizard of a page - click on save without changing the image - set a domain on the website - go to the page with the cover image => result an absolute URL is saved and we get a traceback error when visiting on wrong domain. Cause: The 4c5d9861e389534f9ca684b9faa1ce6289df5639 was only getting relative URL when an image was selected. This didn't work if we open and saved the modal when there was no website_meta_og_img and the image was gotten from the META og:image element. In 19.0, since there was a python fix for existing errors [1] this case was hidden and didn't cause an issue. Fix: Forward-port cdffe8ab905068a3947ea62562c7209d216b2b8d in upper versions. A fix should also be done after to ensure we don't save absolute URL: for example if the image we save matches the og:image in DOM, don't save it. [1]: cdffe8ab905068a3947ea62562c7209d216b2b8d [2]: odoo/upgrade@5408746b110d660901645b9c7b9aa9cee7aaf235 opw-5867113 opw-5874045 opw-5874931 opw-5875254 opw-5884536 opw-5885941 opw-5887081 opw-5888627 opw-5889050 opw-5891942 opw-5897982 opw-5898621 opw-5898731 opw-5899722 opw-5900450 opw-5906008
This update corrects a visual bug where highlights on RTL websites (like Arabic) were incorrectly positioned. The fix adjusts how the highlight element and its associated SVG are positioned, ensuring the highlight appears correctly regardless of the website's language direction. This improves the user experience for international visitors.
Original PR description
Scenario: - add a RTL language to website (eg. arabic) - go to the website and add a highlight to part of a line - switch to RTL language Result: the highlight is not at the correct X position. This…
Scenario:
- add a RTL language to website (eg. arabic)
- go to the website and add a highlight to part of a line
- switch to RTL language
Result: the highlight is not at the correct X position.
This commit fixes the issue for most browser by changing in RTL that:
- the SVG is positionned from the right so the SVG right matches
the boundary rect right
- mirroring the SVG so when the 1x1 pixel is scaled, it is scaled toward
the left and it matches the left boundary rect
This is not always working (mostly for safari) because the positionning
of position:absolute SVG inside highlighted position:relative SPAN is
behavior differently in RTL (an even behave differently in case of mixed
RTL / LTR strings in dir:rtl blocks).
This is reproduced in this code:
https://gist.github.com/nle-odoo/21fea59d338b55b3e2a337cf360ef878
So to fix that issue, after inserting a SVG element in RTL in DOM, we
correct the X position by the current error from what we intended.
opw-5049432
opw-5344412
opw-5867908
## PR NOTE:
### 1) For the part:
```diff
- const firstRect = highlightEl.getClientRects()[0];
+ const rtl = window.getComputedStyle(highlightEl).direction === "rtl";
+ let firstRect;
+ if (rtl) { // Take the first top right element instead of top left
+ firstRect = [...highlightEl.getClientRects()].sort((a, b) => a.top - b.top || (b.left + b.width) - (a.left + a.width))[0];
+ } else {
+ firstRect = highlightEl.getClientRects()[0];
+ }
+
...
- const spanOffsetX = firstRect.x - containerRect.x;
const spanOffsetY = firstRect.y - containerRect.y;
- svg.style.left = `${(rects.x - containerRect.x - spanOffsetX) * scale}px`;
svg.style.top = `${(rects.y - containerRect.y - spanOffsetY) * scale}px`;
svg.style.bottom = `0px`;
- svg.style.right = `0px`;
+ if (rtl) { // Position from the right instead of left and mirror the SVG
+ const spanOffsetX = containerRect.x + containerRect.width - firstRect.x - firstRect.width;
+ svg.style.left = `0px`;
+ svg.style.right = `${(containerRect.x + containerRect.width - rects.x - rects.width - spanOffsetX) * scale}px`;
+ svg.style.transform = 'scale(-1, 1)';
+ } else {
+ const spanOffsetX = firstRect.x - containerRect.x;
+ svg.style.left = `${(rects.x - containerRect.x - spanOffsetX) * scale}px`;
+ svg.style.right = `0px`;
+ }
```
I don't understand why the other SVG are positioned relative to the first one(but the original code did that and making it but with the logic of RTL instead of LTR seems to be the only way to make it work).
Note that in saas-18.3 the logic seemed to be a lot more simple, but there was a "display: inline-block;" on the highlight item which simplified the logic a lot (you can just have 100% width to match the item highlighted), but would make (LTR in RTL content, or RTL in LTR content) "`<highlight>hello</highlight> world`" appear in RTL as "`world <highlight>hello</highlight>`".
Forward-Port-Of: odoo/odoo#226359This update addresses discrepancies in invoice totals, particularly for Peppol transactions, caused by rounding of product prices. The change ensures that invoice totals more closely match original documents by removing fixed decimal precision from 'Product Price' fields. This improves data accuracy and compliance.
Original PR description
Imported invoices can show different totals than what the original document show. This especially an issue for Peppol. Because `price_unit` is rounded, by computing the total of a line with `quantity * price_unit`, it may not be possible to obtain the same total as the one from the original document. To face this issue, the float fields related to "Product Price" don't have a decimal precision set anymore. To keep the UI clean, the precision set on "Product Price" is now interpreted as a "minimal precision". So if it set to 3, we'll see at least 3 digits. If there's more, all the digits are shown. As so: `4.0` -> `'4.000'` `4.23` -> `'4.230'` `4.235` -> `'4.235'` `4.2358` -> `'4.23458'` task-4895014 Forward-Port-Of: odoo/odoo#247064 Forward-Port-Of: odoo/odoo#243987
This update fixes an issue where the HTML editor toolbar would unexpectedly close and not reopen after a link popover was closed. The fix ensures the toolbar correctly reopens when focus returns to the editor, improving the user experience when working with rich text content. This resolves a previous bug that caused cursor issues.
Original PR description
#### Description of the issue this PR addresses: `focusEditable`: - The previous focusEditable logic failed in the website because `this.editable` is `contenteditable="false"` and there is often a…
#### Description of the issue this PR addresses: `focusEditable`: - The previous focusEditable logic failed in the website because `this.editable` is `contenteditable="false"` and there is often a non-editable ancestor near the selection. - As a result, the editor did not receive focus, and focusing the wrong element caused the cursor to collapse or move unexpectedly. `Toolbar not remains open`: - The toolbar closed when focus leaves iframe but not getting reopen when focus returns. ### Desired behavior after PR is merged: - The focusEditable focuses the nearest element with `contenteditable="true"` and then restores the cursor when the selection lies inside a non-editable region. - We dispatch `selection_enter_handlers` when focus returns to the iframe document. - This reopens the toolbar when the selection is not collapsed. task-5261404 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#244970 Forward-Port-Of: odoo/odoo#237953
This update fixes an issue where components added to manufacturing orders through the product catalog weren't correctly transferred to the pre-production warehouse. The fix adds a warehouse ID to the moves created by the catalog, ensuring proper stock movement and fulfilling multi-step manufacturing requirements. This improves the accuracy of inventory tracking.
Original PR description
Issue
-----
In multi step manufacturing, components added to MO through the catalog don't get transfered to the pre-prod location.
Steps to reproduce
-----
- 2 step manufacturing
- Create 2 products
- Create a MO for the first product
- Open the product catalog
- Add some qty of the second product
- Go back to the MO & confirm it
> No procurement transfer for the second product from stock to pre-prod
Cause
-----
The move created by the catalog has no `warehouse_id` so in `adjust_procure_method` we don't find any rule which means it gets set to MTS
https://github.com/odoo/odoo/blob/6ecd271ff34313d900a0ad14b1c20679808ba9b8/addons/stock/models/stock_move.py#L2366-L2368
-----
Ticket:
opw-5221418
Forward-Port-Of: odoo/odoo#243036
Forward-Port-Of: odoo/odoo#239265This update fixes an issue where combo items weren't always printed correctly on preparation printers. Now, the system considers both the combo's and individual item's categories, ensuring all items in a combo are printed as intended. This improves the accuracy of order fulfillment for combo sales.
Original PR description
Previously, combo choice items with categories assigned to a preparation printer were skipped when their category differed from the combo parent product’s category. This commit ensures that both the combo parent product’s category and the item product’s category are taken into account to correctly print items to the preparation printer. Task: 5902389 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#247028
This update enhances the reliability of syncing user data with Google Calendar. Previously, the sync process could time out with a large number of users due to a single, lengthy operation. Now, multiple sync cron jobs are used, targeting different user groups, to distribute the workload and prevent timeouts.
Original PR description
Before this commit, the sync cron of google could only work by performing a search on the users and starting the sync. But the cron could timeout with a large amount of users. As users were fetched in the same order, some users could never be synced. This change allows to create several cron with different type of user in self (by company, department, etc) to allow distribute the sync effort over several crons. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#210286
This update resolves an issue where searching large datasets, particularly with many2many fields, could cause performance problems and errors due to excessive filtering. By adding a context to control grouping, the system now avoids unnecessary searches, improving stability and speed for users. This primarily impacts the Mail and Attachment modules.
Original PR description
Add a context to know if we are grouppnig. This allows us to stop `_search` methods which need to search and filter manually all records. For example, when asking if a field is groupable, `_description_groupable` will run a dummy search for many2many fields, for a normal user searching on ir.attachment, it would search for all attachments and try to filter them in memory leading to OOM error. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update significantly speeds up the process of importing products into Odoo, particularly when dealing with a large number of stock locations. The change optimizes a slow database query, resulting in a much faster import time. This improves overall system performance and reduces import delays.
Original PR description
Problem: When importing products in Inventory, _compute_quantities_dict fetches data from all internal stock.location. For databases with many internal locations (e.g., 37K), the query using LIKE ANY with a large array of parent paths is very slow. Solution: - Replace LIKE ANY(%s) pattern matching with a semi-join subquery using EXISTS, allowing the query to terminate on the first match. - Add an index on (parent_path, id) to convert sequential scans into index-only scans. Benchmark: |Number of rows| Before | After | |--------------|--------|-------| |37K | 4.xxs | 1.xxs | Simplied plan (a few hundred records instead of 37K) |Before|After| |-|-| |https://explain.dalibo.com/plan/8gb1257c6712age5|https://explain.dalibo.com/plan/5ef9c3g7aab3dfag| Related ticket: opw-5500169 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#245939
This update corrects a bug causing dynamic website snippets to flicker in and out of view. The issue stemmed from a mismanaged CSS class, which has now been restored to its original state: snippets should be initially hidden and then displayed based on content. This ensures a consistent and reliable user experience for website visitors.
Original PR description
Steps to reproduce [18.2+]: 1. Add a dynamic snippet to a website page (e.g., Events). 2. Unpublish all event records. 3. The snippet first appears with a visible header, which then disappears. [A]-…
Steps to reproduce [18.2+]: 1. Add a dynamic snippet to a website page (e.g., Events). 2. Unpublish all event records. 3. The snippet first appears with a visible header, which then disappears. [A]- Starting from [1], the `o_dynamic_empty` class was introduced to handle the dynamic snippets visibility, and an upgrade script (see [3]) set this class by default on them. Later in 18.0 (after [2]), the class was changed to `s_dynamic_empty` in the XML template, while on the JS side, the class used to toggle snippet visibility was `o_dynamic_snippet_empty`. This class was also added to snippets on destroy (before saving). [B]- As a result, a dynamic snippet may end up with: - `o_dynamic_empty` & `o_dynamic_snippet_empty`: for old (before 18.0) but edited snippets. - `o_dynamic_empty`: for old snippets never updated in edit mode on 18.0. - `s_dynamic_empty` & `o_dynamic_snippet_empty`: for new snippets created in 18.0. Remark: the `s_dynamic_empty` class was introduced by mistake and does not have any associated CSS Since only `o_dynamic_snippet_empty` has `display: none` in CSS, the interaction flow became inconsistent (starting from 18.2): snippets were initially visible, then hidden if no content was found... which caused the flickering behavior described above. And because of [B], old snippets with the `o_dynamic_empty` class will be visible by default in 18.0. This commit restores the intended (and original) behavior: - A dynamic snippet should be invisible by default, - Then the interaction decides (based on actual content) whether the snippet should be displayed. [1]: https://github.com/odoo/odoo/commit/63def9c87305dd7773e0592a28fe19d0b63c0878 [2]: https://github.com/odoo/odoo/commit/76cf201e1fc356ad00b27bcdec408c54949df33b [3]: https://github.com/odoo/upgrade/commit/af5821d9aeb75d09653fc33f14e98fae5f5ba906 opw-5354523 Forward-Port-Of: odoo/odoo#240807 Forward-Port-Of: odoo/odoo#238305
This update fixes an issue where annual returns incorrectly used a fiscal year filter when a company's fiscal year differed from the calendar year. Now, annual returns always follow the company's fiscal year, ensuring accurate reporting and eliminating confusion for users. This improves the reliability of financial data presented in reports.
Original PR description
When a company fiscal year differs from the civil year, the annual return incorrectly falls back to the report’s FY-aligned year filter. The return should always follow the civil year, so the fallback is skipped and the return period filter is shown instead. task-5511074 Forward-Port-Of: odoo/enterprise#104726
This update resolves an issue preventing the legal validation of annual VAT reports for Luxembourg. The PR adds missing required fields to the XML export, ensuring compliance with tax regulations. This corrects a previous validation error related to specific data fields.
Original PR description
### Issue: The annual VAT report could not be legally validated because some mandatory parent fields were missing in the XML export ### Cause: This PR add some required fields:…
### Issue: The annual VAT report could not be legally validated because some mandatory parent fields were missing in the XML export ### Cause: This PR add some required fields: https://github.com/odoo/enterprise/pull/93357 However, for file validation, the following parent fields are mandatory if certain child fields are present: ``` - Field 129: Field 129 is mandatory if one of the following fields is filled : 771, 971, 772, 972, 774, 773, 973, 124, 128, 197 - Field 137: Field 137 is mandatory if one of the following fields is filled : 776, 976, 777, 977, 778, 978, 134, 136, 198 - Field 145: Field 145 is mandatory if one of the following fields is filled: 781, 981, 782, 982, 783, 983, 142, 144, 199 - Field 163: Field 163 is mandatory if one of the following fields is filled : 791, 991, 793, 993, 797, 795, 995, 158, 162, 200 - Field 175: Field 175 is mandatory if one of the following fields is filled: 396, 162 ``` 164 and 165 are also added according to this assertion: https://github.com/odoo/enterprise/blob/c93388741182f1873054557a6e7767186674fafa/l10n_lu_reports/models/l10n_lu_annual_tax_report.py#L167-L171 ### Note: This PR is related to the 18.0 PR: https://github.com/odoo/enterprise/pull/104785 It also fix issues in `_add_yearly_fields()` because the validation consider form as float instead of dict ### Steps to reproduce: - Install `l10n_lu_reports` and switch to LU company - Open the Tax Report `Annual VAT Declaration` - Export the XML - Notice that codes 396, 394 149, and 153 are present, but 129, 137, 145, 163 and 175 are missing opw-5119920 Forward-Port-Of: odoo/enterprise#106457 Forward-Port-Of: odoo/enterprise#105143
This update corrects a bug where subscriptions with zero-sum quantities resulted in invoices being set to the subscription start date instead of the correct invoice period. The fix ensures accurate invoice date calculations for subscriptions with mixed positive and negative quantities, preventing incorrect billing.
Original PR description
### Issue: When creating a subscription with several lines whose quantities add up to zero, the next invoice date is not updated and set to the start date. ### Steps to reproduce: - Install…
### Issue: When creating a subscription with several lines whose quantities add up to zero, the next invoice date is not updated and set to the start date. ### Steps to reproduce: - Install 'sale_subscription' - Create a new Subscription with two lines and a tart data several months in the past - One with a quantity of 1 and a higher price - The other with a quantity of -1 - It can be the same service product with invoicing based on ordered quantity - Confirm the Subscription - Click "Create Invoice" and confirm the invoice - Back to the Subscription, the next invoice date was not updated. ### Cause: In `_get_max_invoiced_date()` to compute the invoiced periods we check the quantity corresponding to this period. But if an invoice has two lines with opposite quantities, they will cancel each other out at this line: https://github.com/odoo/enterprise/blob/c2ac44f492ec53083864f07ff5bfbff9458ddf2a/sale_subscription/models/account_move_line.py#L131 So the method will return not return the date in `invoice_dates`. Later, if `_get_max_invoiced_date()` returns nothing for `last_invoice_end_date` then `next_invoice_date` is set to `start_date`: https://github.com/odoo/enterprise/blob/c2ac44f492ec53083864f07ff5bfbff9458ddf2a/sale_subscription/models/account_move.py#L66-L67 ### Solution: The goal was to not include invoices that were fully refunded for the `last_invoice_end_date`. This is why `_get_max_invoiced_date()` substract the quantities from refunds. To make this work we can take the absolute value of the quantity returned by the compute method before giving it the wanted sign based on if it's an invoice or a refund. opw-5360930 Forward-Port-Of: odoo/enterprise#106364 Forward-Port-Of: odoo/enterprise#103705
This update ensures that freight costs are now accurately included in the customs documents generated for international sales. Previously, these costs were missing, leading to potential discrepancies in customs declarations. This change aligns with SendCloud API specifications and improves the accuracy of international shipping documentation.
Original PR description
Issue ----- For international deliveries, the customs document does not include the freight costs. Steps to reproduce ----- - Create an international sale (eg BE -> US) - Validate delivery - Open the commercial invoice > Freight costs is set to 0 Change ----- The `freight_costs` should be included in the `customs_information` field of the request (along with all customs-related data, as other fields have been deprecated) https://api.sendcloud.dev/docs/sendcloud-public-api/branches/v2/parcels/operations/create-a-parcel#:~:text=object%2E-,customs%5Finformation ----- Ticket: opw-5486742 Forward-Port-Of: odoo/enterprise#106387 Forward-Port-Of: odoo/enterprise#105543
This update resolves an error that occurred when employees were linked to multiple commission plans using the same payslip input. The fix ensures accurate currency conversion for commissions, preventing a system error and guaranteeing correct payslip generation for users with multiple commission plans. This improves payroll accuracy and reliability.
Original PR description
Currently, an error occurs while generating a payslip for an employee who is linked to more than one commission plan using the same payslip input. **Steps to Reproduce:** 1. Install the…
Currently, an error occurs while generating a payslip for an employee who is linked to more than one commission plan using the same payslip input. **Steps to Reproduce:** 1. Install the hr_payroll_sale_commission module. 2. Create a user and link to an employee. Set a contract for the employee. 3. Create two commission plans for the same user: - Use the same Payslip Input in both plans. - Set the Target Frequency to "Monthly" for both. 4. Generate a payslip for the employee. Ref: [Video](https://drive.google.com/file/d/1HhtUL2xznS_Aoi9ePL0OJLdGaXU8ZFZR/view?usp=sharing) **Error:** `ValueError - Expected singleton: sale.commission.report(30026010100009, 40026010100009)` **Cause:** When multiple commission records belong to the same payslip input, it tries to convert the commission amount using `coms.commission`, where coms has multiple recordsets. This leads to a singleton error during currency conversion. **Fix:** This commit ensures the currency conversion is applied per commission and prevents the singleton error. sentry-7187854690 Forward-Port-Of: odoo/enterprise#106124 Forward-Port-Of: odoo/enterprise#104464
This update fixes an issue where WhatsApp messages to blacklisted numbers wouldn't be blocked if the recipient's country differed from the sender's company. The fix ensures that all international phone numbers are correctly processed, regardless of the sender's location, preventing unwanted messages. This improves compliance and protects users from spam.
Original PR description
Sending a WhatsApp message to a blacklisted number fails to be blocked if the recipient's phone number country differs from the sender company's country. ### Steps to reproduce 1. Configure a…
Sending a WhatsApp message to a blacklisted number fails to be blocked if the recipient's phone number country differs from the sender company's country.
### Steps to reproduce
1. Configure a WhatsApp account.
2. Set the Company's country to Germany (+49).
3. Create a Contact with a Belgian phone number (e.g. +32456001122).
4. Send a template message to this contact.
5. Have the contact reply with "STOP" to opt-out (this correctly adds +32456001122 to the blacklist).
6. Send another message to the contact.
- Expected: The message is blocked.
- Actual: The message is sent successfully.
### Root cause
The blacklist search logic relies on implicit phone number sanitization which behaves incorrectly for international numbers without a `+` prefix.
1. `whatsapp.message` stores numbers as `CountryCode + NationalNumber` without a `+` (e.g. "32456001122").
2. `phone.blacklist` stores numbers in E.164 format with a `+` (e.g. "+32456001122").
3. When searching `phone.blacklist` with "32456001122", the system interprets it as a local number for the Company's country (Germany) because of the missing `+`.
4. It reformats the search term to German E.164 ("+4932456001122").
5. The query fails to match the actual blacklisted number ("+32456001122"), allowing the message to pass.
### Fix
Explicitly prepend a `+` to the recipient's number before searching the blacklist. This forces the validation logic to parse the number as international (E.164), bypassing the company-country bias and ensuring the search term matches the stored blacklisted number.
opw-5401789
Forward-Port-Of: odoo/enterprise#106395
Forward-Port-Of: odoo/enterprise#104556This update resolves an issue where the quantity of components in a manufacturing order wasn't correctly updated after exiting the barcode MRP operation. Specifically, the system incorrectly handled reserved quantities, leading to inaccurate component tracking. This fix ensures that component quantities are accurately reflected after the operation completes.
Original PR description
**Issue** When leaving the barcode MRP operation, `post_barcode_process()` may incorrectly update the move quantities. **Steps to reproduce** - Create a product with a BOM using a component with qty…
**Issue** When leaving the barcode MRP operation, `post_barcode_process()` may incorrectly update the move quantities. **Steps to reproduce** - Create a product with a BOM using a component with qty 6. - Create an MO producing qty 1. - Open the Barcode app > Manufacturing > open the MO (remove “MO Ready” filter if needed). - Click “+1”. - Edit the component qty from 6 to 3. - Exit the operation. - Re-enter the operation. -> The component shows 3/3 instead of 3/3 and 0/3. **Cause** On exit, `_onExit`: https://github.com/odoo/enterprise/blob/776848dc4e29d07a027847fde46a59f84dd35f56/stock_barcode/static/src/models/barcode_picking_model.js#L1489 calls `post_barcode_process()`, which triggers `split_uncompleted_moves`: https://github.com/odoo/enterprise/blob/776848dc4e29d07a027847fde46a59f84dd35f56/stock_barcode/models/stock_move.py#L16 correctly creating a `stock.move.line` with qty 3. However, `_truncate_overreserved_moves`: https://github.com/odoo/enterprise/blob/776848dc4e29d07a027847fde46a59f84dd35f56/stock_barcode/models/stock_move.py#L40 then reduces the move quantity to `max_reserved_qty = 3` and unreserves the remaining 3 units: https://github.com/odoo/enterprise/blob/776848dc4e29d07a027847fde46a59f84dd35f56/stock_barcode/models/stock_move.py#L49 This happens because the newly created move line is initialized with `reserved_uom_qty = 0`: https://github.com/odoo/enterprise/blob/776848dc4e29d07a027847fde46a59f84dd35f56/stock_barcode/static/src/models/barcode_picking_model.js#L1256 leading to `max_reserved_qty = quantity_done = 3 < move.quantity = 6`, while `move.product_uom_qty` is still 6. opw-5166763 Forward-Port-Of: odoo/enterprise#104199 Forward-Port-Of: odoo/enterprise#100314
This update resolves an issue where CFDI payroll validation failed when users created payrolls with no deductions. The fix ensures that the CFDI report accurately reflects the absence of deductions, aligning with Mexican tax regulations. This prevents validation errors and ensures compliance.
Original PR description
…eductions Currently, if users modify the MX Payroll structure in order to have no deductions in the final payroll, CFDI validation for the payroll entry will fail. Steps to reproduce: - Set up…
…eductions
Currently, if users modify the MX Payroll structure in order to have no deductions in the final payroll, CFDI validation for the payroll entry will fail.
Steps to reproduce:
- Set up Payroll Structure "Mexico: Regular Pay" with Salary Rules:
- Used subsidy:
- Code: SUBSIDY
- Category: Allowance
- CFDI Concept: (O02) Employment Subsidy (Effectively Delivered to the Worker)
- Deduction:
- Code: DEDUCTION
- Category: Deduction
- CFDI Concept: (D04) Others
- Net Salary:
- Code: NET
- Category: Net
- CFDI Concept: (P01) Salaries, Wages, Stripes, and Day Labor
- Formula: `result = payslip.paid_amount`
- In Payroll > Payslips, Click 'New Off-Cycle'
- Select employee, compute sheet, create draft journal entry and post it
- Back to the payslip, mark as paid and generate CFDI
Issue:
CFDI Validation will fail with error
`Code : 301 Message : Error en complemento Nómina. [Error #NOM38] El atributo Nomina.TotalDeducciones, no debe existir. Folio: 0002. Serie: SLR/2025/12.`
It occurs because, according to the official specs [1] attribute `TotalDeducciones` should not be reported in case there are no deductions
[1] http://omawww.sat.gob.mx/tramitesyservicios/Paginas/documentos/GuiallenadoNomina311221.pdf
opw-5348789
Forward-Port-Of: odoo/enterprise#104311This update resolves an issue where sign requests created on older Odoo versions (before 16.0) would fail due to missing communication company information. The fix automatically uses the user's company date format in these cases, ensuring sign requests can be processed correctly. This prevents crashes and improves the reliability of the sign request workflow.
Original PR description
For old databases that were created before 16.0, existing sign request might not have a communication company set. Following commit odoo/enterprise@6b505a34f7bdee89c155eed7507296d5acfd8a9b trying to…
For old databases that were created before 16.0, existing sign request might not have a communication company set.
Following commit odoo/enterprise@6b505a34f7bdee89c155eed7507296d5acfd8a9b trying to open such sign request will result in a crash:
```
Traceback:
...
File "/data/build/odoo/enterprise/saas-18.3/sign/controllers/main.py", line 354, in get_document
context = self.get_document_qweb_context(request_id, token)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/enterprise/saas-18.3/sign/controllers/main.py", line 88, in get_document_qweb_context
date_format = posix_to_ldml(lang.date_format, locale=locale)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/odoo/odoo/saas-18.3/odoo/tools/misc.py", line 606, in posix_to_ldml
for c in fmt:
TypeError: 'bool' object is not iterable
```
This commit fallback to the create user's company to determine the date language when there is not communication company set.
no-task (from feedback pad)
Forward-Port-Of: odoo/enterprise#87526This update fixes an issue where the business card scanner button disappeared from the mobile version of the CRM. The change restores the button's functionality, allowing users to easily scan business cards directly within the CRM's mobile interface. This ensures a seamless experience for mobile users adding leads.
Original PR description
After the introduction of the lead generation dropdown (task-4876662) in the CRM kanban control panel, the business card scanner button was no longer rendered on mobile devices. This commit restores the business card scanner button in the kanban control panel on mobile. Task-5899751
This update ensures salary configuration details (like address and personal information) are automatically populated when creating contracts from templates. Previously, templates didn't use employee data, but this change now leverages the employee's latest version, streamlining the offer creation process. This improves data accuracy and reduces manual input.
Original PR description
The personal informations in the salary config is prefilled using the version selected in the offer. When making a new offert for an already employed person, the default version is the last active version, the address and other personal info are already set on that version and the salary has the last up-to-date data. But when selecting a contract template in an offer, the version does not have the personal info from the employee (as it's a template). In this commit, we force to use the employee itself (from the active version of the employee, or the employee linked to the contract template copy - created during the offer creation). may it be an applicant or an existing employee, when an offer is generated, an employee is created (or re-used) and set on the contract template. So it works in every case. Taks-5162703 Forward-Port-Of: odoo/enterprise#104375 Forward-Port-Of: odoo/enterprise#99908
This update resolves an issue where payment reports were inconsistently using different export formats (NACHA or localization-specific). The fix ensures that payment reports now automatically use the correct format based on the company's localization, improving report accuracy and usability for users. The changes have been backported to version 18.0 and include new tests.
Original PR description
\* = l10n_{ae, au, ch, in, sa, us}_hr_payroll + hr_payroll_account_iso20022
Issue:
The current behavior looks deterministic: when clicking on "Create Payment Report" it -sometimes- shows the current company's export format by default, other times it shows the "NACHA" type. Or it could be the last installed module's export format value for the other companies.
Solution:
I fixed it in this PR: https://github.com/odoo/enterprise/pull/93683 and now backporting the changes to version 18.0
task-5189295
Forward-Port-Of: odoo/enterprise#104377
Forward-Port-Of: odoo/enterprise#100126