Friday, March 13, 2026
43 changes · saas-19.1
New functionality added to Odoo
This update automatically generates Danish FIK payment references on customer invoices through sales journals. Users simply configure their bank's FIK creditor number, ensuring compliant Danish FIK payments without disrupting existing workflows. This simplifies accounting for Danish businesses.
Original PR description
Before: - Danish companies had to rely on manual or non-standard payment communication on invoices. - They could not generate official FIK payment references. After: - Sales journals can now generate Danish FIK payment references automatically. - Users configure an 8-digit bank-issued FIK creditor number on sales journal. Impact: - Enables compliant Danish FIK payments without changing user workflows. Related PR: https://github.com/odoo/enterprise/pull/102612 taskID-5401553 Forward-Port-Of: odoo/odoo#240829
Enhancements to existing features
This update introduces a new button in the order management interface that allows users to quickly move all orders to the next stage of processing. When an order reaches the final stage, the preparation status is automatically marked as complete, improving workflow efficiency. This change simplifies order management and reduces manual effort.
Original PR description
In this commit: =============== - We added a `Clear All Orders` button in the sidebar. On clicking that, all the orders will be moved to their next respective stage. - If the order stage is already the last stage, then the order's preparation state is marked as done. Task: 5877460 Forward-Port-Of: odoo/enterprise#105847
Resolved issues and error corrections
This update fixes an issue where the phone number input field on mobile devices was difficult to use due to overlapping buttons. The fix hides the button labels and adjusts the input width to ensure a clear and easy editing experience. This enhances usability for mobile users.
Original PR description
Steps to reproduce: 1. Install `contacts` 2. Create an individual contact with a phone number 3. Try to edit the phone number on the mobile Issue: - Unable to edit in mobile view Cause: - On mobile…
Steps to reproduce:
1. Install `contacts`
2. Create an individual contact with a phone number
3. Try to edit the phone number on the mobile
Issue:
- Unable to edit in mobile view
Cause:
- On mobile devices, the utility buttons (Call, SMS, WhatsApp) inside the phone widget consume significant horizontal space. Due to the flex layout, this forces the actual phone input field to shrink too much, making it hard/impossible to view or edit the number.
Solution:
- Hide the text labels of the utility buttons to save space, showing only the icons
- make input's width 100% on mobile screens in partner form
<table>
<thead>
<tr>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">
<img
src="https://github.com/user-attachments/assets/a620d417-119e-4e28-a62b-f63031e72598"
alt="Before"
width="500"
/>
</td>
<td align="center">
<img width="500" height="354" alt="image" src="https://github.com/user-attachments/assets/6adc4c77-767d-491d-a468-8463c0f77666" />
</td>
</tr>
</tbody>
</table>
opw-5489021
Forward-Port-Of: odoo/odoo#246295This update enhances the Turkish localization for Odoo, specifically addressing issues related to invoice generation and VAT compliance. Key changes include mandatory fields for tax exemption reasons and improved handling of UBL invoice generation, ensuring accurate and compliant invoices for Turkish businesses.
Original PR description
This commit adds the following improvements and bug fixes to the turkish localization: - Make shipping method required for GiB export invoices - Make Exemption Reason mandatory when Invoice Type is Tax Exempt - Ensure Invoice Type is selected when Invoice Scenario is set - Hide the nilvera send status for Vendor Bills - Adjust the error message for missing CTSP numbers on invoice lines - Allow resetting Vendor Bills to draft - Give priority to the currency rate on the invoice when generating UBL - Create a new bridge module to bypass the VAT validation for test VAT numbers - Fix bug in bulk customer verification task-5868201 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249247
This change optimizes the process of generating GST reports by streamlining the database query. Specifically, it removes a complex domain filter that caused performance issues with large datasets. This results in faster report generation times, improving efficiency for users.
Original PR description
If account.move and account.move.line have big data then domain with create problme ORM create sub query like this ``` SELECT account_move.id FROM account_move WHERE (…
If account.move and account.move.line have big data then domain with create problme ORM create sub query like this
```
SELECT
account_move.id
FROM
account_move
WHERE
(
account_move.l10n_in_gst_return_period_id = 23
OR (
account_move.move_type IN ('in_invoice', 'in_refund')
AND account_move.invoice_date >= '2025-11-01'
AND account_move.invoice_date <= '2025-11-30'
AND account_move.company_id IN (1)
AND account_move.state = 'posted'
AND (
account_move.l10n_in_gst_treatment NOT IN ('composition', 'unregistered', 'consumer')
OR account_move.l10n_in_gst_treatment IS NULL
)
AND account_move.id IN (
SELECT
account_move_line.move_id
FROM
account_move_line
WHERE
EXISTS (
SELECT 1
FROM account_move_line_account_tax_rel AS account_move_line__tax_ids
WHERE account_move_line__tax_ids.account_move_line_id = account_move_line.id
)
)
)
)
ORDER BY
account_move.date DESC,
account_move.name DESC,
account_move.invoice_date DESC,
account_move.id DESC
```
See this EXPLAIN for big database
```
Gather Merge (cost=165759176482.82..2983665158687.50 rows=36 width=30)
Workers Planned: 2
-> Incremental Sort (cost=165759175482.80..2983665157683.32 rows=18 width=30)
Sort Key: account_move.date DESC, account_move.name DESC, account_move.invoice_date DESC, account_move.id DESC
Presorted Key: account_move.date
-> Parallel Index Scan Backward using account_move__date_index on account_move (cost=59.28..2983665157682.51 rows=18 width=30)
Filter: ((l10n_in_gst_return_period_id = 23) OR (((move_type)::text = ANY ('{in_invoice,in_refund}'::text[])) AND (invoice_date >= '2025-11-01'::date) AND (invoice_date <= '2025-11-30'::date) AND (company_id = 1) AND ((state)::text = 'posted'::text) AND (((l10n_in_gst_treatment)::text <> ALL ('{composition,unregistered,consumer}'::text[])) OR (l10n_in_gst_treatment IS NULL)) AND (SubPlan 1)))
SubPlan 1
-> Materialize (cost=58.84..1601427.18 rows=4994548 width=4)
-> Merge Semi Join (cost=58.84..1556944.44 rows=4994548 width=4)
Merge Cond: (account_move_line.id = account_move_line__tax_ids.account_move_line_id)
-> Index Scan using account_move_line_pkey on account_move_line (cost=0.44..1339780.32 rows=26611459 width=8)
-> Index Only Scan using account_move_line_account_tax_rel_pkey on account_move_line_account_tax_rel account_move_line__tax_ids (cost=0.43..88678.65 rows=4994548 width=4)
```
So removing this from domain and put it as condition it's faster
Forward-Port-Of: odoo/enterprise#110334
Forward-Port-Of: odoo/enterprise#109795This update streamlines the timesheet assistant by simplifying labels and UI elements, while also enhancing the accuracy of time calculations and resolving display issues. Key changes include restricting access to the billable status field and optimizing how project information is stored for better performance.
Original PR description
[IMP] {helpdesk,sale,project}_timesheet_{,enterprise,forecast}: timesheet assistant generic improvements
In this Commit,
- Assistant Form > "Billable" boolean hidden for users without Sales access rights
- Assistant Form > Labels updated:
- "Project Name" → "Project"
- "Task Name" → "Task"
- "Time Spent" → "Time"
- "Save Changes" → "Save"
- Assistant Form UI Improved by applying same changes done in master,
REF: https://github.com/odoo/enterprise/pull/104347
- Assistant Form > create and edit option removed for projects
- Suggestions logic reviewed for better results
- Correct time calculation for chronological grouping
- Unmatched project display issues resolved in both suggestions and local config
- Local Config List view aligned with Odoo UI views
- Local Config Storage limited to project/task/ticket IDs instead of `display_name`
and `id`
task-5902077This update fixes an error in how outstanding amounts are calculated when a down payment is reversed with a credit note. Previously, the system incorrectly produced negative amounts, leading to inaccurate settlement calculations. The fix ensures the correct outstanding balance is displayed and processed, improving financial accuracy.
Original PR description
When having a down payment that is reversed by a credit note, the amount unpaid is wrongly computed. This is because we take the sum of invoice lines price total, regardless they come from invoice or credit note. Therefore we end up with negative value. Steps: - Have a SO for 500 - Make a downpayment for 300, confirm - Make a credit note for the downpayment invoice, confirm -> SO's amount unpaid is -100, it should be 500. If you now settle the SO, the amount unpaid will be -300 instead of 0. opw-5175562 Forward-Port-Of: odoo/odoo#253135 Forward-Port-Of: odoo/odoo#233248
This update resolves an issue where expense reports created from incoming emails weren't being generated due to a company mismatch. The fix ensures the system always uses the employee's company affiliation when creating the expense, regardless of the user's default company setting. This prevents errors and allows for seamless expense reporting from email.
Original PR description
**Steps to reproduce:** - Install Expenses - Activate "Incoming Emails" in the settings - Configure the expense Alias - Configure an "Incoming Mail Server" - Create a Branch for a company - Create a…
**Steps to reproduce:** - Install Expenses - Activate "Incoming Emails" in the settings - Configure the expense Alias - Configure an "Incoming Mail Server" - Create a Branch for a company - Create a User: * Email Address: [an existing email address] * Allowed Companies: [the parent company + the branch company] * Default Company: [the branch company] * User Types: Internal User - Create an employee for the user in the parent company - From the email address, send a PDF to the expense alias **Issue:** The expense is not created in the database due to a UserError: "Incompatible companies on records". **Cause:** When the email is received and treated, the system tries to create an expense. From the email address, it retrieves an employee that is linked to the expense. For the company of the expense, if a user is linked to the employee, it takes the default company of the user. Otherwise, it takes the company of the employee. In this case, the company set on the expense is the default company of the user (i.e. the branch company) and the employee set on the expense belongs to the parent company ; which triggers the UserError during the company check. **Solution:** Always use the company of the employee, even if there is a user linked to the employee. opw-5346809 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253313 Forward-Port-Of: odoo/odoo#249415
This update corrects a validation error that occurred when sending invoices to Peppol. The system previously used an outdated unit code ('QT') which is no longer compliant with UN/ECE standards. This fix ensures invoices meet current regulatory requirements for international exchange.
Original PR description
Currently, the Odoo UoM 'qt (US)' is converted to 'QT', which is not valid anymore. Based on investigation, this was originally set to QT following this link: https://unece.org/fileadmin/DAM/cefact/recommendations/rec20/rec20_rev3_Annex2e.pdf But this document seems dated from 2005. Step to reproduce: - Create an invoice with a line with 'qt (US)' as UoM - Try to send the invoice to Peppol - You will get a validation error: "[BR-CL-23]-Unit code MUST be coded according to the UN/ECE Recommendation 20 with Rec 21" Also removed the link to unece.org since the link is no longer valid. opw-5961476 Forward-Port-Of: odoo/odoo#252803 Forward-Port-Of: odoo/odoo#252174
This update resolves an issue where purchase events weren't sending the correct data to Google Analytics. The fix converts a JSON string received from the website into a proper object, ensuring all purchase details (like transaction ID and value) are accurately tracked. This improves the reliability of our e-commerce analytics.
Original PR description
## Description The `Tracking` interaction's `setup()` method reads order tracking info from the HTML `data-order-tracking-info` attribute and passes it directly to `_trackGa()` → `gtag()`. Since the…
## Description The `Tracking` interaction's `setup()` method reads order tracking info from the HTML `data-order-tracking-info` attribute and passes it directly to `_trackGa()` → `gtag()`. Since the DOM `dataset` API always returns strings, `gtag()` receives a JSON string instead of an object, causing GA4 to silently drop all purchase event parameters (`transaction_id`, `value`, `items`, etc.). Compare with `onAddToCart()` in the same file, which receives its data via `CustomEvent.detail` (already a JS object) and works correctly. **Impacted versions:** - 19.0 **Steps to reproduce:** 1. Configure a Google Analytics key in Website > Settings 2. Add a product to cart and complete checkout 3. On `/shop/confirmation`, inspect the dataLayer or GA4 debug view **Current behavior:** - `add_to_cart` event fires with correct ecommerce parameters (object) - `purchase` event fires with a JSON **string** instead of an object — GA4 silently drops the parameters **Expected behavior:** - `purchase` event fires with a parsed object containing `transaction_id`, `value`, `currency`, `tax`, `items` **Fix:** Add `JSON.parse()` to convert the data attribute string back to an object before passing it to `gtag()`. --- I hereby confirm I have signed the Odoo CLA (included in this PR as `doc/cla/corporate/comma.md`). Forward-Port-Of: odoo/odoo#253074
This update ensures invoices are generated correctly by only using bank accounts authorized for outgoing payments. The system now prioritizes customer and payment journal banks, preventing errors and improving the overall stability of the point-of-sale invoicing process.
Original PR description
Before this commit: --- - Invoice generation could fail when the selected partner or company bank did not allow outgoing payments. - The first available bank account was used without checking whether it was valid for out payments. After this commit: --- - Select only bank accounts that allow outgoing payments. - Prioritize customer banks for refunds, then payment journal banks, and finally company banks as fallback. - Prevent errors caused by untrusted or unsupported bank accounts. task-5954530 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253158 Forward-Port-Of: odoo/odoo#250062
This update ensures accurate sub-line total calculations in the stock barcode module. The change requires the ‘stock.group_production_lot’ setting to be active, which was missing in previous versions, causing test failures. This fix ensures correct aggregation of line totals when processing stock movements.
Original PR description
This issue occurs on Single App and Single L10n, without demo data ### Summary This part of the test verifies that the sub line totals are calculated correctly, which from 18.3 requires the…
This issue occurs on Single App and Single L10n, without demo data ### Summary This part of the test verifies that the sub line totals are calculated correctly, which from 18.3 requires the stock.group_production_lot setting to be active. Specifically, it validates that the sum accurately reflects the Unit of Measure (UOM) across various packagings. https://github.com/odoo/enterprise/blob/93e3c6f13fbab8d54694648d04908e451f1e97fc/stock_barcode/static/tests/tours/tour_test_barcode_flows_picking.js#L6472-L6498 ### Observation The grouping logic is contingent on the stock.group_production_lot setting. If this setting is inactive, the system fails to group lines, preventing the calculation of the aggregate total. Without the production lot group active, the conditional checks will bypass the grouping process: https://github.com/odoo/enterprise/blob/d664e1f97f6e7fa462b4cf1806322a54762c0de4/stock_barcode/static/src/models/barcode_model.js#L53 https://github.com/odoo/enterprise/blob/d664e1f97f6e7fa462b4cf1806322a54762c0de4/stock_barcode/static/src/models/barcode_model.js#L224-L225 When the demo data are enabled [the group is implied](https://github.com/odoo/odoo/blob/8a7ca8beac521f41faf79a6022935fdbb605de76/addons/stock/data/stock_demo.xml#L185-L187) ### Impact When stock.group_production_lot is disabled: - Lines remain ungrouped. - The total sum of the grouped line is never generated. - The test fails as it cannot find or validate the expected sub-line totals. This issue originate from the 18.3 forward port of this [commit](https://github.com/odoo/enterprise/commit/84d4b1f144e8a437fe76ec5ef3bc9799cdf993b0) runbot-241109 Forward-Port-Of: odoo/enterprise#108908
This update fixes an issue where cancelled stock moves were incorrectly impacting the calculation of kit costs in sales orders. The fix ensures that only completed, finished stock moves are used when determining the value of kits, leading to more accurate sales reporting. This improves the reliability of sales order pricing.
Original PR description
Currently cancelled moves are also being used when getting the value. This is already done in the main method: https://github.com/odoo/odoo/blob/049321aa5e0d4271050b406477bac5fb788b410b/addons/stock_account/models/account_move_line.py#L67 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253028
This update addresses a memory issue that occurred when calculating depreciation, particularly with large numbers of asset records. The fix utilizes a more efficient method to process the data, preventing the system from running out of memory and ensuring stable performance. This resolves a problem previously seen in the 16.0 version.
Original PR description
The previous compute method loaded all moves records into memory, which caused an out-of-memory issue for large number of record. Replaced the logic with read_group aggregation to perform the…
The previous compute method loaded all moves records into memory, which caused an out-of-memory issue for large number of record. Replaced the logic with read_group aggregation to perform the calculation using sql and reduce memory usage.
Note: the issue is faced during 16.0 version too but as 16.0 is no more supported for bug fix. So, doing it from 17.0 version.
```
Traceback (most recent call last):
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 333, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 346, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 506, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 657, in mock_view_tree
self.mock_web_search_read(model, view, [domain], fields_list)
File "/tmp/tmpkvo8a96w/migrations/base/tests/test_mock_crawl.py", line 691, in mock_web_search_read
data = model.search_read(domain=domain, fields=fields_list, limit=80, order=filter_order(model))
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5074, in search_read
result = records.read(fields, **read_kwargs)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3038, in read
return self._read_format(fnames=fields, load=load)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3219, in _read_format
vals[name] = convert(record[name], record, use_name_get)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 6007, in __getitem__
return self._fields[key].__get__(self, self.env.registry[self._name])
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1222, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1404, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/16.0/addons/mail/models/mail_thread.py", line 403, in _compute_field_value
return super()._compute_field_value(field)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 4276, in _compute_field_value
fields.determine(field.compute, self)
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 98, in determine
return needle(*args)
File "/home/odoo/src/enterprise/16.0/account_asset/models/account_asset.py", line 293, in _compute_value_residual
posted_depreciation_moves = record.depreciation_move_ids.filtered(lambda mv: mv.state == 'posted')
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5496, in filtered
return self.browse([rec.id for rec in self if func(rec)])
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 5496, in <listcomp>
return self.browse([rec.id for rec in self if func(rec)])
File "/home/odoo/src/enterprise/16.0/account_asset/models/account_asset.py", line 293, in <lambda>
posted_depreciation_moves = record.depreciation_move_ids.filtered(lambda mv: mv.state == 'posted')
File "/home/odoo/src/odoo/16.0/odoo/fields.py", line 1187, in __get__
recs._fetch_field(self)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3245, in _fetch_field
self._read(fnames)
File "/home/odoo/src/odoo/16.0/odoo/models.py", line 3351, in _read
self.env.cache.insert_missing(fetched, field, values)
File "/home/odoo/src/odoo/16.0/odoo/api.py", line 1123, in insert_missing
field_cache.setdefault(id_, val)
MemoryError
```
opw-5921410
upg-3891767
Forward-Port-Of: odoo/enterprise#109008This update ensures that our UY e-invoicing process can correctly validate invoices by granting necessary permissions to access company data. Previously, users without specific group access would encounter validation errors. This change resolves a technical issue preventing proper invoice processing for Uruguay.
Original PR description
This pull request makes a small update to the `_ucfe_inbox` method in `l10n_uy_edi_document.py` to ensure that company-specific fields are always accessed with the appropriate permissions. This is achieved by using the `sudo()` method when retrieving the `l10n_uy_edi_ucfe_commerce_code` and `l10n_uy_edi_ucfe_terminal_code` fields from the `company` record. * Ensured that `l10n_uy_edi_ucfe_commerce_code` and `l10n_uy_edi_ucfe_terminal_code` fields are accessed with elevated permissions by calling `company.sudo()` in the `_ucfe_inbox` method (`l10n_uy_edi_document.py`). Without this fix, if the user doesn't belong to group "base system", it won't be able to validate CFEs, receiving the following message: <img width="1272" height="400" alt="image" src="https://github.com/user-attachments/assets/ec4223fb-5b96-4a3e-babf-2f6a35ecd123" /> Forward-Port-Of: odoo/enterprise#105918
This update resolves latency issues experienced on iOS devices when interacting with the Point of Sale system. The fix involves adjusting how the system responds to touch input, specifically addressing differences between iOS and Android devices. Additionally, pinch-zoom functionality has been disabled to ensure a smoother user experience.
Original PR description
On IOS devices, there was a latency issue when hitting different elements in the POS and self. Actually, the issue is because IOS devices don't react in the same way as Android devices. IOS adds a delay of +/-300ms when the element is not considered as a button. Instead of replacing a lot of elements with a button element we can add the parameter role="button". I also disabled the pinch zoom in the POS, self and preparation display. It's mandatory to add the parameter touch-action: pan-x pan-y to the * selector. task: 5976364 enterprise pr : https://github.com/odoo/enterprise/pull/109483 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251198
This update resolves latency issues experienced by users on iOS devices when interacting with the Point of Sale system. The fix addresses differences in how iOS and Android devices respond to user input, specifically by adding a 'role="button"' parameter to elements. Additionally, pinch-zoom functionality has been disabled to ensure a smoother user experience.
Original PR description
On IOS devices, there was a latency issue when hitting different elements in the POS and self. Actually, the issue is because IOS devices don't react in the same way as Android devices. IOS adds a delay of +/-300ms when the element is not considered as a button. Instead of replacing a lot of elements with a button element we can add the parameter role="button". I also disabled the pinch zoom in the POS, self and preparation display. It's mandatory to add the parameter touch-action: pan-x pan-y to the * selector. task: 5976364 community pr : https://github.com/odoo/odoo/pull/251198 Forward-Port-Of: odoo/enterprise#109483
This update resolves an issue preventing users with multiple companies from successfully setting up their Amazon accounts. The fix allows access to all company data during the onboarding process, ensuring compatibility with connected Amazon accounts. This improves the onboarding experience for all Odoo Enterprise users.
Original PR description
The onboarding return route is a website route with access restricted to the website company only. This causes an error when the company doesn't match the Amazon account being connected. This commit allows users to access all their companies during Amazon account setup to avoid this mismatch error. opw-5944078 Forward-Port-Of: odoo/enterprise#109882 Forward-Port-Of: odoo/enterprise#109590
This update resolves a problem where the media dialog in the product editor would sometimes hang indefinitely. The fix ensures that the UI is always released after an action, regardless of its outcome, and improves the loading process for media assets. This prevents frustrating delays for users adding images to product pages.
Original PR description
*: website_sale Commit [1] added a UI block when doing a reloadable operation, and unblocked it once the action finished. However, if the action didn't complete, `ui.unblock` would never be called,…
*: website_sale Commit [1] added a UI block when doing a reloadable operation, and unblocked it once the action finished. However, if the action didn't complete, `ui.unblock` would never be called, leaving the UI blocked indefinitely. To reproduce the issue in website_sale: - Install Website & eCommerce - Go to /shop page - Open a product page - Open the editor - Click on the main product image - In the "Images" section > Click on "Add more" in the Extra media field - Popup shows up but it loads indefinitely Fix this by always calling `ui.unblock` regardless of the reload outcome. Also move the media dialog opening to `load`, which runs before the UI is blocked, passing the selected media as `loadResult` to `apply`. [1]: https://github.com/odoo/odoo/commit/453b7eb8e038ee8e8a54de16fc1a45fb2fab573a Co-authored by: Robin Lejeune (role) <role@odoo.com> opw-6003505, opw-6006393, opw-6016898, opw-6013484, opw-6014383 Forward-Port-Of: odoo/odoo#253025 Forward-Port-Of: odoo/odoo#252755
This update resolves an issue where user edits in the mass mailing editor were lost when switching tabs in the Notebook. The fix ensures that changes are saved promptly and prevents data inconsistencies, improving the user experience and data integrity.
Original PR description
Main issue: Prior to this commit, updateValue would guarantee that `body_arch` and `body_html` were always updated in sync (to avoid an inconsistent state where the user thinks they updated the…
Main issue:
Prior to this commit, updateValue would guarantee that `body_arch` and
`body_html` were always updated in sync (to avoid an inconsistent state where
the user thinks they updated the mailing, and they see the new html in the
editor, but the email html is obsolete and would be sent as is).
However this caused another issue, that the user would lose their work when
switching tab in the Notebook, because computing the `body_html` may be slower
than the view patch to switch tab (`updateValue` is interrupted). In such a
case, neither `body_arch` nor `body_html` was updated on the record, and when
the user comes back to edit them, they see that all changes were lost.
To prevent this, a new strategy is adopted:
- `body_arch` is now updated as soon as possible to save the latest user
changes
- `body_html` is set to an empty string to avoid inconsistencies, and in order
to trigger `convert_inline` automatically the next time the
`mass_mailing_html_field` is instanced without any user action.
- after `convert_inline`, if `updateValue` was not aborted, the record is
updated again with the new value for `body_html`
Minor issues:
1) Prior to this commit, the iframe would flicker during `convert_inline`
because it was done inside that very iframe, and the `convert_inline` needs a
specific width (1320px) for it to work properly, meaning that if the iframe was
not at that specific dimension, it was resized temporarily for that process.
This commit introduces hooks to execute the `convert_inline` process in a
separate iframe, outside of the user view, which removes this flickering.
2) Prior to this commit, assets for readonly/basic editor/builder were all
loaded inside the iframe, and then toggled on/off depending on which were
needed. Since the `convert_inline` process is moved in another iframe, it's as
good time as any to deprecate this toggling (as it could be a bit unreliable and
could cause some flickering when unloading/reloading the style). There is now a
separate asset bundle for the 3 use case, and only one of them is loaded per
iframe depending on the needs.
3) Prior to this commit, `body_html` was hard-coded as a dependency of the
`mass_mailing_html_field`, and that dependency lacked the `required` attribute,
which should depend on the value of `body_arch`. The dependency is now added in
the related views, and the field is now generic. This also prevents the user
from leaving the view if `convert_inline` could not be completed successfully.
4) Prior to this commit, switching to another view through `doAction` could
throw an error if the field was dirty, as the `form view` would be destroyed
before `commitChanges` had the time to be completed. Now, `commitChanges`
promise is properly awaited by the `action_service` if the field is dirty before
`doAction` (unless `forceLeave` is true).
5) Prior to this commit, the record was updated through a `blur` event on the
iframe window. However, it means that every time the iframe looses focus when
the users interacts with the builder, a popover or the form status indicator,
that blur event would fire, triggering the `convert_inline` process. This commit
reduces the amount of such updates by only triggering the update outside of
these elements, as we don't need to update the record value while the user is
still actively editing the mailing.
Blur handlers/props are deprecated with this commit and will be removed further
down the line.
6) Ensure that in the rare case where a `html_field` value is exactly the same
on different records, the `html_field` state key is updated (triggers a
wysiwyg/mass_mailing_iframe reset).
7) Remove an erroneous part in `onWillUpdateProps` of `mass_mailing_html_field`
which could display the theme selector again on the same record just after
selecting a theme if props were updated.
8) Ensure `withBuilder` getter of `mass_mailing_html_field` properly reads the
state activeTheme every time it is used (if it does not, it could cause issues
with the reactivity, since reading on the state is required for a property
subscription).
9) Remove a useless `onWillUpdateProps` of `mass_mailing_iframe` which was never
used because when `props.showCodeView` changes, the iframe is always destroyed,
so there is no need to update its state.
10) Deprecate usage of `<meta http-equiv="X-UA-Compatible" content="IE=edge"/>`,
to be removed further down the line, as it is useless in the modern web.
11) Ignore errors during a builder "Operation" that was not finished before the
editor was destroyed. In `mass_mailing`, the editor is expected to be
destroyable synchronously to work inside an Odoo view, unlike in `website`.
What's already in the DOM just before destruction will be updated on the
`record`, and the rest of the operation will be lost. However, an attempt is
made to wait for ongoing operations at the start of the
`HtmlField.commitChanges`.
12) Ensure correct visibility option state
Prior to this commit, the `dataAttributeChangeAction` selected item depended on
the domain value computed during the last template rendering, compared to the
current edited element value. The issue is that when an edited element receives
a new `data-filter-domain`, the selected options are evaluated before the
component can register the new domain in its state, so the wrong values are
compared. In this particular case, since we only need 2 values (on/off), an
acceptable trade-off is to choose the selected item ("always visible" vs
"conditionally") based on the Boolean value of the attribute.
13) Remove deprecated assets toggle test
The toggle assets feature was deprecated in a prior [commit1].
The test is removed as its outcome is non-deterministic, because it depends on
the `target` property of `event` returned as a promise resolution value by
`loadBundle`, however the browser can set that target to `null` after the event
was dispatched, so relying on the target value to keep track of the inserted
link is not reliable.
Since that `toggle` feature is not used anymore, it is not needed to run a test
for it. The feature will be removed in the latest `dev` branch.
[commit1]: https://github.com/odoo/odoo/commit/a0aa581636e257894c6c7e87c3793edebecad303
14) Prevent crash on commitChanges if editor is not ready
Prior to this commit, various checks in `commitChanges` did not take into
account that the editor could be instanced but not ready yet (meaning that
plugins are not available, and it is not possible to extract the editable
content).
This commit ensures that `commitChanges` can not crash if called when the editor
is not ready.
15) Properly keep track of dirtiness
mass_mailing changes related to [commit2], which added a way to keep track of a
specific change handled during one `commitChanges` call. The field should stay
dirty if it received changes during a `commitChanges` execution.
In mass_mailing specifically, there were 2 other situations with invalid
tracking of dirtiness:
a) A new record with no change could not be discarded as it was incorrectly
marked as dirty since the `inlineField` value is "".
After this commit, the field is marked as dirty only if the edited field value
is not "" while the `inlineField` value is "", which is the problematic
situation where both values are desynchronized. A new record with both values at
"" is not marked as dirty anymore.
b) Setting a new theme in mass_mailing did not communicate properly with the
relational model about dirtiness.
After this commit, using `setThemeHTML` triggers `onChange`, and the record
update properly tracks that change to communicate with the
`FormStatusIndicator`. The field `isDirty` property stays at `true` though,
because it still needs to execute `convertToEmailHtml` to compute the
`inlineField` value, and it needs the `editor` for that. A `commitChanges`
occurs `onEditorReady` to execute this computation, at the end of which the
field is finally set as not dirty.
[commit2]: https://github.com/odoo/odoo/commit/378580735c785bdcf8b184342834d2b3ddaaaedd
16) Prevent crash with null selection
`document.getSelection()` returns `null` when the selection is not in the
document. However the selection plugin `isSelectionInEditable` function only
support a selection object or `undefined` as an argument, and will crash with
`null`.
This commit ensures that a valid value is provided to the plugin function to
prevent crashes where the selection is moved outside of the `mass_mailing`
iframe before `normalize_handlers` execution.
task-5976348
Forward-Port-Of: odoo/odoo#250883This update fixes a problem where AI translations on the SaaS website would fail after multiple requests due to rate limits. The fix reduces the number of simultaneous requests and now displays a helpful message if some translations are missed, ensuring a smoother user experience. This prevents users from needing to restart the translation process entirely.
Original PR description
Scenario: - be on odoo SaaS instance - be on non-translated page with enough content to do 4 requests to /html_editor/generate_text (that are done in chunk of 2000 characters per request currently) -…
Scenario:
- be on odoo SaaS instance
- be on non-translated page with enough content to do 4 requests
to /html_editor/generate_text (that are done in chunk of 2000
characters per request currently)
- open the editor and use "Translate to {lang}" (ai translation)
Result: you see a message "Connection lost. Trying to reconnect..." and
after waiting 10-20 seconds, no translation are inserted in the page.
In reality the requests after the 3 first ones were cancelled (with
error 429 too many requests) by nginx, and the 3 first ones worked
correctly but their result was not used because of the error of the
other ones.
Fix:
- decrease the number of concurrent request from 5 to 3 which is the
current default for this route on SaaS
- adapt the code so if there is errors on one request, successfull
requests will still be applied with the text "Translation Error.
{number} text blocks were skipped during translation. Please try
again." for the blocks that were missed.
This way even if there is an error, the translation is not totally
blocked and doesn't need to be restarted from zero (making it impossible
in the original scenario).
Side note: the number of text blocks not translated was a multiplication
of the total number of text blocks by the number of failed response.
This fix adapts it to just the total of words substrating the number of
translation applied.
opw-5892402
Forward-Port-Of: odoo/odoo#250611This update increases the time allowed for payment processing to prevent interruptions caused by network issues or device timeouts. It also adds detailed logging with a unique transaction ID to track payments from start to finish, improving traceability and troubleshooting.
Original PR description
Reason: = - Network Connectivity: Terminal devices send continuous heartbeat checks to the API. Network fluctuations can cause heartbeat failures. - Configuration Discrepancy: Devices have a 60-second processing limit, while the server timeout was set to 30 seconds. In this commit: = - Increased Request timeout from 35s to 60s to prevent premature failures due to device/server timeout mismatch and network delays. - Added SourceID to system logs for improved end-to-end transaction traceability. task-6012679 Forward-Port-Of: odoo/odoo#252420
This update resolves a problem preventing Odoo from correctly handling signed invoices submitted by Italian Public Administration. The issue stemmed from incorrect data types being used when updating invoice attachments, leading to errors and duplicate transaction attempts. This ensures proper invoice processing for Public Administration partners in Italy.
Original PR description
Currently, if we try to update the existing `l10n_it_edi_attachment_file` with the signed data received during the submission of an invoice (Invoices for Italian Public Administration businesses must…
Currently, if we try to update the existing `l10n_it_edi_attachment_file` with the signed data received during the submission of an invoice (Invoices for Italian Public Administration businesses must be signed, handled on the IAP side), it fails. The problem is that in this specific flow, the 'attachment' variable contains a binary rather than attachment_data. Unfortunately, I could not find a complete flow to reproduce the issue, as there is no flow that sends an invoice to SdI while the l10n_it_edi_attachment_file variable is already set in the move, except maybe via manual import of an attachment into the invoice. Expected flow: - User creates a move with `l10n_it_edi_attachment_file` (unspecified how) - User sends the move to SdI for a Public Administration partner - IAP signs the attachment and sends it back to Odoo - Odoo raises an error because it tries to use dictionary features on a binary field - Odoo does not save the transaction ID, and if the user tries to resend the move, a Duplicate Error occurs from the SdI side. Ticket [link](https://www.odoo.com/odoo/project.task/5954645) opw-5954645 Forward-Port-Of: odoo/odoo#252966
A bug was causing accrual leave calculations to be delayed by one month. This update corrects a logic error in the system that was incorrectly applying accruals based on the previous year's carry-over date, resulting in missed accruals for February. This ensures accurate leave accrual calculations going forward.
Original PR description
steps to reproduce: ------------------- 1. Install Time Off 2. Go to Configuration > Accrual Plans 3. Create an accrual plan: * Set the accrued gain time to "At the start of the accrual period" * Set…
steps to reproduce: ------------------- 1. Install Time Off 2. Go to Configuration > Accrual Plans 3. Create an accrual plan: * Set the accrued gain time to "At the start of the accrual period" * Set the carry-over time to "At the start of the year" 4. Create a milestone: * Set the number of accrued days to 1 * Set the accrual frequency to "monthly" and the carry over to "None.Accrued time reset to 0" 5. Go to Management > Allocations 6. Create an allocation: * Set the start date to 2025-01-01 * Set the accrual plan to the one created above 7. Use future allocations to check accruals current behavior: ----------------- - On 2026-01-01 --> accrued days = 1 (correct) - On 2026-02-01 --> accrued days = 1 (should be 2) - On 2026-03-01 --> accrued days = 2 (delayed accrual, off by one month) cause of the issue: ------------------- Commit 30c7011 introduced a condition that accrues time off on the carry over date: https://github.com/odoo/odoo/blob/1416aad902a97ce56aaecc2aadc4dd9f7814ee53/addons/hr_holidays/models/hr_leave_allocation.py#L559 This incorrectly evaluates accruals across the carry over period instead of restricting to the current month, causing February accruals to be skipped. **Reason February accruals are skipped:** https://github.com/odoo/odoo/blob/dcb072f675c5630327d27d785b86e1ec8e2d442d/addons/hr_holidays/models/hr_leave_allocation.py#L559-L561 https://github.com/odoo/odoo/blob/dcb072f675c5630327d27d785b86e1ec8e2d442d/addons/hr_holidays/models/hr_leave_allocation.py#L541-L544 * After January, the last_executed_carryover_date is set to 2026-01-01. * Therefore, February uses last_executed_carryover_date = 2026-01-01. * The condition evaluates as true for February: ```python3 last_executed_carryover_date <= allocation.nextcall <= carryover_period_end 2026-01-01 <= 2026-02-01 <= 2026-02-01 ``` As a result, the February accrual is skipped. **Why it works correctly in March:** * After February, the last_executed_carryover_date is updated to 2027-01-01. * March now uses this updated date: ```python3 last_executed_carryover_date <= allocation.nextcall <= carryover_period_end 2027-01-01 <= 2026-03-01 <= 2027-02-01 ``` The condition is not satisfied, so accruals are processed correctly. solution: ---------- Add a condition to check if the loop has already run for the current carryover period. This ensures the system avoids applying the carryover twice, allowing subsequent accruals to process as expected. opw-5020834 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253409 Forward-Port-Of: odoo/odoo#227646
This update resolves an issue where the original product name was incorrectly prepended to product descriptions on invoices and purchase orders when using translated product names. The fix ensures that only the translated name and description are displayed, improving clarity and accuracy for users working with multi-language customers.
Original PR description
**Steps to reproduce: 1. Install invoicing app 2. Add French language in the settings 3. Create a customer with language set as French 4. Create a product and define french translations of the name…
**Steps to reproduce: 1. Install invoicing app 2. Add French language in the settings 3. Create a customer with language set as French 4. Create a product and define french translations of the name and the description in Sales tab 5. Create an invoice for that customer and choose the product you created 6. You will find the translated product name and description under the product name 7. Edit the description, save and preview the invoice 8. The invoice line will contain [Product Name EN] [Product Name FR] [Product Description FR] **Description of the issue: When creating an invoice for a customer whose language differs from the user's account language, manually editing the product description on an invoice line causes the original product name to be prepended to the description. The same issue happens in a RFQ in Purchase. **Expected behaviour: User can edit the product description in the invoice line and the output in the invoice should only be the translated name and description, without the original product name. **Why this happens? 1. When the product is selected in the invoice line, the label is loaded from _compute_name method in account_move_line, which holds the translated name and description. 2. After editing the description and escaping the field (clicking outside it), the parseLabel method is called, which prepends the original name to the label, making the invoice output as [original name] [translated name] [translated desc.] **The fix Added translated_product_name computed field to follow a similar flow as the sale quotation which is already working as intended. Fix is done in Invoice and Purchase. opw-5480494 Forward-Port-Of: odoo/odoo#248401
This update fixes an issue where using a delivery address in the POS for invoicing incorrectly calculated Cost of Goods Sold (COGS). The fix ensures accurate COGS accounting by correctly linking the invoice to the relevant stock movements, resolving discrepancies in expense and output account balances.
Original PR description
When a delivery address is selected as the customer in the POS UI and an invoice is generated from the POS order, it results in two different `partner_id` being set on the `pos.order` and the…
When a delivery address is selected as the customer in the POS UI and an invoice is generated from the POS order, it results in two different `partner_id` being set on the `pos.order` and the `account.move`. It is expected, as a delivery address cannot logically be used as an invoicing address. Anglo-saxon accounting registers the COGS with additional account.move.line on the invoice and, when using real time valuation, the balance of these lines is calculated from values found on the corresponding `stock.move`. Currently, the `stock.move` cannot be found if the `partner_id` on the `pos.order` and the `account.move` are different. The system then falls back on the `standard_price` of the `product_id`, which is incorrect. In version 19+, the `product_id` used to calculate the unit price is fetched from the `stock.move` but, because it's an empty recordset, the balance of the COGS is 0 and the lines are not created. An easy fix could be to remove this check of equivalence between the two `partner_id`. The invoice is created directly from the POS order anyway. I am not sure why it is necessary. Am I missing something? Steps to reproduce: 1. Create a product with fifo and automated valuation. Make sure that the product type is storable. 2. Validate one purchase and its delivery for the product (qty 5, unit price 5). 3. Validate another purchase and its delivery for the product (qty 5, unit price 10). 4. Configure the point of sale to allow invoicing. 5. Open a pos session then sell 1 item of the product. Select a delivery adress as the customer and generate an invoice. 6. Since the product is fifo, this means that the cost of goods sold is 1 * 5. 7. The correct expense account line should have balance of 5.0. 8. The correct output account line should have balance of -5.0. 9. The COGS lines instead have a balance of 8.13 and -8.13 which corresponds to the standard price of the product at the time of the invoice. Related ticket: opw-5467877 Forward-Port-Of: odoo/odoo#245208
This update ensures that prepaid amounts for Malaysian credit, debit, and refund notes (specifically document types 02, 03, 04, 12, 13, and 14) are correctly set to zero, aligning with Malaysian e-Invoicing (MyInvois) API requirements. The changes also update payable amounts to accurately reflect the full invoice total, improving data consistency for e-invoice generation.
Original PR description
Currently, the `prepaid_amount` in the UBL export is calculated as `amount_total - amount_residual` for all document types. However, for credit notes, debit notes, and refund notes (both standard and self-billed, corresponding to document type codes 02, 03, 04, 12, 13, and 14), this amount should be 0 to comply with Malaysian e-Invoicing (MyInvois) API requirements. This commit introduces the following fixes: - Sets the `prepaid_amount` to 0 for document types '02', '03', '04', '12', '13', and '14'. - Update the `payable_amount` to the full `invoice.amount_total`. Task-5971843 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253321 Forward-Port-Of: odoo/odoo#251915
This update resolves an issue where removing a product from a sales order, purchase order, or invoice didn't actually remove it from the order. The fix corrects a technical error in how the system identified the correct section to update, ensuring products are properly removed and the catalog functions as expected. A related test was also updated to ensure proper initialization.
Original PR description
Steps to reproduce: 1. Create a new SO/PO/Invoice and add a product. 2. Add a new section below the product. 3. Open the catalog and click the Remove button for the added product. Issue: - The…
Steps to reproduce: 1. Create a new SO/PO/Invoice and add a product. 2. Add a new section below the product. 3. Open the catalog and click the Remove button for the added product. Issue: - The product is not removed from the SO/PO/Invoice. Cause: - When removing the product, the 'No section' entry is also removed if it becomes empty. - As a result, `this.env.searchModel.selectedSection.sectionId` point to the first remaining section in the order. - Because of this incorrect reference, the wrong `section_id` is passed in the params, and `update_order_line_info` does not update the intended order line. Fix: - Use `this.env.selectedSectionId` instead of `searchModel.selectedSection.sectionId` to ensure the correct `section_id` is always passed. After applying this fix, `test_catalog_vendor_uom` tour was failing because in tour execution the kanban records are mounted before the search panel finishes initializing the selected section. As a result, the initial section state is not yet stabilized when the price is asserted. To address this: - Update the tour to explicitly wait until the "No section" entry is marked as selected in the search panel before asserting the product price, ensuring the catalog is fully initialized. opw-5960140 Forward-Port-Of: odoo/odoo#250103
This update ensures Odoo complies with new NACHA regulations regarding payment descriptions. Starting March 2026, all payroll payments must include 'PAYROLL' in the Company Entry Description field to avoid potential payment issues. This change is a necessary update to maintain compliance and ensure smooth financial transactions.
Original PR description
Starting March 20, 2026, NACHA requires the Company Entry Description field to contain "PAYROLL" for paying wages, salaries, or compensation [1]. [1] https://www.nacha.org/rules/risk-management-topics-company-entry-descriptions task-5981941 Forward-Port-Of: odoo/enterprise#109460
This update resolves an issue where 'View more' and 'View less' options within the eCommerce product filters were not translated when browsing in languages other than English. The fix ensures consistent, localized labels across all supported languages, improving the user experience for international customers. This was achieved by correctly implementing translation functions within the website_sale module.
Original PR description
When browsing an eCommerce in any language but English and trying to filter on an attribute with more than 8 values and at most 20, the "View more" and "View less" options are not translated Steps to…
When browsing an eCommerce in any language but English and trying to filter on an attribute with more than 8 values and at most 20, the "View more" and "View less" options are not translated Steps to reproduce: 1. Install eCommerce 2. Create a product with one attribute that has 9 to 20 values and publish the product to the eCommerce (the attribute should have radio display type and should be visible in the eCommerce) 3. Add a language (e.g. French) and translate the eCommerce's website 4. Open the website and set the language to French 5. In the left column, open the filter for the attribute previously created 6. Click on "Voir plus" 7. "View less" is not translated, if you click on it, "View more" is not translated anymore Issue: The translation for "View more" is generated because it is present in the template `filter_radio_and_multi_attributes` but when we update the text in website_sale.js, the terms are not translated anymore Solution: Use `_t` to translate the "View more" and "View less" terms opw-5985712 Forward-Port-Of: odoo/odoo#252828
This update fixes an issue where preparation tickets weren't printed correctly when using the mobile self-order feature. The team corrected a previous change that inadvertently stopped initializing preparation printers for mobile mode, ensuring tickets are now printed as expected. This improves the user experience for mobile order preparation.
Original PR description
Steps to reproduce ------------------ 1. Setup a preparation printer for PoS 2. Enable "mobile" self order 3. From self order, make an order -> Notice it's not been sent to the preparation display. Reason ------ In c72f119dceb390e8c4e054905f359b835861f0ba, we added support for LNA, and part of that, we stopped initializing the preparation printers for "mobile" mode; that seems like a mistake, as prep printers can also be used to print the preparation tickets when self ordering using kiosk mode, but also mobile mode! Fix --- Initialize the prep printers for "mobile" mode too. opw-5904620
This update optimizes the process of deleting `mail.activity` and `mail.message` records linked to `voip.call` records. Previously, a slow scan occurred due to missing indexes, causing delays. Adding indexes significantly speeds up these deletions, improving overall system responsiveness.
Original PR description
Description ----------- Commit odoo/enterprise@5751f93c53d3cf37ae8cb627fb8d10a81b7b8833 adds a few new `Many2one` fields, but they're are not indexed, leading to a `Seq.Scan` on `voip.call` when deleting a `mail.activity` or `mail.message`, whos tables are usually large. This commit adds an index on the fields to speed up the deletion. Benchmark --------- Deletion of a `mail.activity` on a database with a `voip.call` table with ~13M rows. (on hot) | Before | After | |--------|---------| | 2.3s | 0.85 ms |
This change ensures Odoo invoices sent to the AFIP web service (ARCA) comply with their strict requirements for numeric fields like price and quantity. By limiting these values to a maximum of 3 decimal places, we prevent invoice rejections and maintain accurate accounting data. This update aligns with the AFIP specifications and ensures consistent rounding across all monetary amounts.
Original PR description
… request ARCA requires numeric fields such as unit price and quantity to have a maximum of 12 integer digits and 6 decimal places. If these fields are sent with more than 6 decimals, AFIP rejects…
… request ARCA requires numeric fields such as unit price and quantity to have a maximum of 12 integer digits and 6 decimal places. If these fields are sent with more than 6 decimals, AFIP rejects the invoice with errors like: `Code 1814: Campo Cmp.Items.Pro_precio_uni invalido. El valor debe tener 12 enteros y 6 decimales como máximo.` To ensure compliance, values are formatted before sending the request to ARCA. **Precision rationale** ARCA WS documentation mentions 4 decimal places, while the WS error message itself refers to 6 decimals, and in practice the service accepts up to 6 decimals without rejection. In this implementation, we intentionally use 2 decimal places. The reason is consistency with the rest of the monetary amounts in the invoice: line totals, invoice total, taxes, and related amounts are all rounded to 2 decimals, even in cases where the documentation allows higher precision (e.g., 3 decimals). Before the changes in rounding precision, the stable version already rounded values according to line rounding. In real-world accounting scenarios, the vast majority of use cases operate with 2 decimal places. Keeping this behavior ensures consistency across calculations and avoids discrepancies caused by mixed rounding strategies. For a stable release, this was considered the safest and most predictable option, even though the WS technically allows higher precision. Stable version changes are covered in the following commits: https://github.com/odoo/odoo/pull/243987/changes/8a21ec45f9d72a7c80d9c1f8398fe01e298ae775 https://github.com/odoo/odoo/pull/246347/changes/79ceeed707ef274f19a04e741f6cb8ac60c44321 <img width="780" height="435" alt="image" src="https://github.com/user-attachments/assets/9f25a0e8-b9d2-4ad2-bbcf-e988c7f8a4c9" /> [WSFEX - Manual de desarrollador](https://www.afip.gob.ar/ws/WSFEX/WSFEX-Manualparaeldesarrollador.pdf) Forward-Port-Of: odoo/enterprise#110218 Forward-Port-Of: odoo/enterprise#106509
A bug preventing users from copying the two-factor authentication secret via the portal has been resolved. The update ensures the copy button functionality works correctly after enabling two-factor authentication. This improves the security and usability of the Odoo portal.
Original PR description
__Problem__ Since odoo/odoo@e3da5f1 the onclick listener set on `copyButton` is lost because we give the HTML of the body as argument at the dialog creation. __Steps to reproduce__ 1. Go to `/my/security` 2. Click on "Enable two-factor authentication" 3. Confirm password 4. Click on "Cannot scan it?" 5. The "Copy" button doesn't work __Fix__ - Inherit from `InputConfirmationDialog` to add a listener to the button. - At the same time, remove the remaining jQuery dependency in this part of the code Forward-Port-Of: odoo/odoo#253314 Forward-Port-Of: odoo/odoo#251429
This update fixes an issue where component pick transfers weren't correctly linking to all relevant manufacturing orders (MOs) when using a two-step manufacturing process (pick then manufacture). The fix ensures that all MOs associated with a sales order are linked to the pick transfer, improving order fulfillment accuracy. This prevents potential delays and errors in the manufacturing process.
Original PR description
Current behavior --- When confirming 1 SO with 2 products with 1 BoM and 1 Rerouting Rule with 0 min/max, with warehouse rule pbm (2 steps: Pick then manufacture), it creates a picking transfer with…
Current behavior --- When confirming 1 SO with 2 products with 1 BoM and 1 Rerouting Rule with 0 min/max, with warehouse rule pbm (2 steps: Pick then manufacture), it creates a picking transfer with only 1 MO attached. Expected behavior --- The picking transfer should have 2 MO's. Steps to reproduce --- 1. Create 2 Products with different BoM's, keep per-product routes empty. 2. Set reordering rules for both to route: Manufacture. 3. Go to warehouses config and set manufacture rule to 2 step (pick -> manufacture) 4. Confirm a SO with those 2 products. Cause of the issue --- If we don't have any Make-to-Order routes for a product, the Make-to-Stock default rule of the warehouse would be used. In such case, all MO's related to such OP (orderpoint/warehouse) would be linked into one picking. The stock.picking model uses related fields to compute product_ids, which calculates relation using next(...) in the ORM. This takes only the first MO's stock move and ignores the second, hence ignoring other production groups. Fix --- Instead of using related fields, use compute to access every relavent production ids. --- opw-5442012 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#249996
This update fixes an issue where the system wasn't properly reflecting demand for dependent components (CMPS) within the MPS planning process. Previously, it defaulted to the oldest BoM, leading to inaccurate demand calculations. Now, the system correctly utilizes the BoM selected by the user, ensuring accurate component demand forecasting.
Original PR description
## Issue: When computing the product tree, the system would use `_bom_find` to find the BoM. However, it's possible to have multiple BoM for the same product, and the user should have chosen which…
## Issue:
When computing the product tree, the system would use `_bom_find` to find the BoM. However, it's possible to have multiple BoM for the same product, and the user should have chosen which BoM he wants to use. `_bom_find` ignores the user configuration in MPS, and simply select the first (oldest) BoM in the list. This means that the components in the MPS would not be correctly updated.
---
## How to reproduce:
https://github.com/user-attachments/assets/c7e6f4d4-332a-4e2b-a40a-1b831daeb6c8
- Create Products FNS & CMP
- Create BoM for FNS without bom line (V1)
- Create BoM for FNS with CMP in bom lines (V2)
- Add FNS to MPS using bom V2
- Set Forecast Qty of FNS to 10
- => Indirect Demand Qty for CMP is not shown (because it's 0)
---
## Test Result without fix:
```
2026-03-05 15:00:24,601 52396 INFO oes_test_18.0 odoo.addons.mrp_mps.tests.test_mrp_mps: Starting TestMpsMps.test_indirect_multiple_boms ...
2026-03-05 15:00:24,742 52396 INFO oes_test_18.0 odoo.addons.mrp_mps.tests.test_mrp_mps: ======================================================================
2026-03-05 15:00:24,742 52396 ERROR oes_test_18.0 odoo.addons.mrp_mps.tests.test_mrp_mps: FAIL: TestMpsMps.test_indirect_multiple_boms
Traceback (most recent call last):
File "/home/odoo/Odoo/src/18.0/enterprise/mrp_mps/tests/test_mrp_mps.py", line 1556, in test_indirect_multiple_boms
self.assertEqual(forecast_cmp['forecast_ids'][0]['indirect_demand_qty'], 10)
AssertionError: 0.0 != 10
```
---
OPW-5979738
Forward-Port-Of: odoo/enterprise#110374
Forward-Port-Of: odoo/enterprise#109693This update ensures that Danish SEPA payments are correctly formatted with the required FIK reference, resolving an issue where the payment XML was missing this crucial detail. The change also strengthens the system's ability to handle country-specific payment reference formats, improving future-proofing and compliance.
Original PR description
Issue: - A related PR introduced Danish FIK payment references on customer invoices. - The generated SEPA payment XML did not include this reference, resulting in missing structured communication for Danish payments. IMP: - Extended the SEPA payment XML generation to include the Danish FIK reference when present. - Refactored the structured reference XML builder to use lxml elements instead of string-based XML construction, ensuring proper escaping of structured references. Impact: - Ensures compliant Danish SEPA payments with correct FIK references. - Makes SEPA XML generation future-proof for country-specific structured references containing non-numeric characters. Related PR: https://github.com/odoo/odoo/pull/240829 Task: 5401553 Forward-Port-Of: odoo/enterprise#102612
This update resolves recent performance issues experienced when using the Point of Sale (POS) and self-ordering systems on iOS devices. The team optimized the user interface by adding styling to improve responsiveness and reduce delays when interacting with elements, resulting in a smoother user experience.
Original PR description
There was some issues when touching elements in the POS and self. We added the parameter role="button" to the elements that were not already and a pe-none to the images. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#253583
This update fixes an issue where landed cost invoices were incorrectly assigning accounts, leading to inaccurate financial reporting. The fix ensures the correct default account (expense) is used for landed costs, aligning with expected inventory valuation and improving financial accuracy.
Original PR description
**Problem:** the default account suggested for landed cost (with real time category) are not the good ones. **Steps to reproduce:** - create a storable product with perpetual average category -…
**Problem:** the default account suggested for landed cost (with real time category) are not the good ones. **Steps to reproduce:** - create a storable product with perpetual average category - create a landed cost (a service product with 'is a landed cost' checked in the purchase tab) - create a category for the landed cost with perpetual valuation - confirm a purchase order for 10 quantity of the product with a unit price of 10 - validate the receipt - confirm quotation for 3 of the product, validate the delivery and confirm the invoice - create a bill for the purchase order - on the invoice lines, unhide the product column - add an invoice line with the landed cost product, for a quantity of 1 and a price of 10 - confirm the bill - click on create landed cost - select the receipt in the transfers field - validate - click on the journal entry on the landed cost form **Current behavior:** On the bill, for the landed cost : - stock valuation is debited of 10 - account payable is credited of 10 (which makes the total credit 110 for account payable) On the journal entry linked to the landed cost: - stock valuation is debited of 7 - stock valuation is credited of 7 So in total there is a debit of 10 in stock valuation and a credit of 10 in account payable. Which does not reflect that part of the products are out of stock. **Expected behavior:** If the expense account was used, both on the bill and on the landed cost, (which is already the case for landed cost with periodic category) the account move lines would be: On the bill : - Expense is debited of 10 - account payable is credited of 10 (which makes the total credit 110 for account payable) On the journal entry linked to the landed cost: - stock valuation is debited of 7 - Expense is credited of 7 So in the total there is : - a credit of 10 in account payable - a debit of 7 in stock valuation - a debit of 3 in expense This is what we want, because the debit of 7 in stock valuation reflect that we only increase the valuation by 7 because only 7 products are still in stock. The debit of 3 in expenses compensate for the cogs. Indeed when we invoiced the SO, the cogs where of 30 but, after the landed cost, valuation wise, the products actually exited the stock with a value of 33 total (11 each). **Cause of the issue:** For the bill: when you create the new account move line and enter the product, _compute_account_id is called to compute the default account for the line. In the stock override, _eligible_for_stock_account is called on the line https://github.com/odoo/odoo/blob/3542c542eac5b204e69a8dd6ae1907cfcef60af3/addons/stock_account/models/account_move_line.py#L18-L19 Because of the stock_landed_costs override, the return value is true https://github.com/odoo/odoo/blob/3542c542eac5b204e69a8dd6ae1907cfcef60af3/addons/stock_landed_costs/models/account_move.py#L78-L82 So the account is changed to stock valuation https://github.com/odoo/odoo/blob/3542c542eac5b204e69a8dd6ae1907cfcef60af3/addons/stock_account/models/account_move_line.py#L23-L24 For the landed cost: - if we create it by selecting 'create landed cost' on the bill : the account id is set in button_create_landed_cost https://github.com/odoo/odoo/blob/3542c542eac5b204e69a8dd6ae1907cfcef60af3/addons/stock_landed_costs/models/account_move.py#L34 -if we create the landed cost, from adjustment/landed cost and selecting new : the expense account is already selected **fix:** In both cases, the client can already manually set the accounts they want, the fix is about having the right default accounts. opw-5941753 Forward-Port-Of: odoo/odoo#251766
This update resolves an issue preventing Argentinian companies with 'IVA Sujeto Exento' (VAT exempt) AFIP responsibility types from creating 'Export Invoices' document types. Previously, this restriction was in place, but this fix now correctly allows the creation of export invoices for these companies, ensuring accurate reporting and compliance. This change improves functionality for a key segment of our Argentinian users.
Original PR description
**Steps to reproduce:** - Install l10n_ar - Create a Argentinian company with "AFIP Responsibility Type" set to "IVA Sujeto Exento" (VAT exempt) - Switch to the created company - In Accounting settings, set up "AFIP Web Services" - Create a journal for export invoices - Create a customer with "AFIP Responsibility Type" set to "Cliente del Exterior" - Create an invoice - Select the created customer - Try to set the document type for export invoices **Issue:** It is not possible to select "(19) EXPORT INVOICES" as "Document Type" for companies having "AFIP Responsibility Type" set to "IVA Sujeto Exento". It is not because the company is "VAT exempt" that it should not be able to create an export invoice. opw-5974268 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252232
This update resolves an issue where loyalty reward products were sometimes hidden within the Point of Sale (PoS) system. Previously, a product designated as a reward could be obscured, preventing customers from selecting it. This change ensures that loyalty reward products are always visible and available for use in the PoS, improving the customer experience and accurate reward redemption.
Original PR description
Before this commit, a product used as a loyalty reward could be hidden in the PoS. opw-5918550 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#251285 Forward-Port-Of: odoo/odoo#248481
This update fixes a problem where payments processed through Authorize.Net were occasionally failing due to a conflict between updates to payment records. By adding a temporary lock to the payment record, Odoo now ensures that payment tokens are used only once, preventing errors and correctly marking successful payments.
Original PR description
Currently, when processing a payment through Authorize.Net, a concurrent update (e.g., from a background cron job) can trigger a PostgreSQL `SERIALIZATION_FAILURE` right after the API request succeeds. Because Odoo automatically retries the request upon this failure, the second attempt sends the same One-Time-Use (OTS) token. Authorize.Net rejects the reused token ("Invalid OTS Token"), causing a successful charge to be incorrectly marked as failed in Odoo.
This commit introduces a pessimistic lock (`FOR NO KEY UPDATE`) on the `payment_transaction` record before making the call to Authorize.Net. This serializes access to the transaction row, ensuring that any lock waits or serialization failures occur *before* the single-use token is consumed, allowing Odoo's automatic retry mechanism to succeed safely.
opw-5475032
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#252370
Forward-Port-Of: odoo/odoo#249088This update fixes a potential issue where the Point of Sale system wasn't reliably displaying orders correctly. The change ensures the system waits for all orders to fully load before rendering, preventing display problems caused by delays in data processing or UI animations. This improves the overall user experience for Point of Sale transactions.
Original PR description
Updated the assertion to use the :count() pseudo-selector directly in the trigger. Instead of synchronously throwing an error as soon as .ticket-screen mounts, the framework will now correctly wait for the exact number of .order-row elements to render, resolving timing issues with pending requests or UI animations. build_error-241246 Forward-Port-Of: odoo/odoo#253781