Daily updates from Odoo
Wednesday, January 14, 2026
45 changes · master
New functionality added to Odoo
This update reflects new regulations from the Mexican government (DOF) regarding Employment Subsidy calculations for 2026. The UMA subsidy percentage has been adjusted to 15.59% starting January 1st, 2026, and 15.02% starting February 1st, 2026. This ensures compliance with current tax laws.
Original PR description
As per the DOF publication on December 31, 2025, the UMA percentages used to calculate the Employment Subsidy have been updated for 2026. New values: - From Jan 1st, 2026: 15.59% - From Feb 1st, 2026: 15.02% This commit adds these new parameter values to "Mexico: UMA Percentage for Subsidy". Reference: https://www.dof.gob.mx/nota_detalle.php?codigo=5777649&fecha=31/12/2025 target: 19.0 task-5488347 Forward-Port-Of: odoo/enterprise#104053
This update adds support for Xendit's new payment channels in Thailand, Malaysia, and Vietnam. This expansion allows our business to accept payments through these local payment methods, broadening our reach and improving customer convenience.
Original PR description
Xendit has expanded to TH, MY and VN supporting the local payment channels. This commit is to add the supported pamyent channels according to what they have added. task-4334511 Forward-Port-Of: odoo/odoo#243430 Forward-Port-Of: odoo/odoo#189527
This update adds the expiration date of product lots to invoices, aligning with industry standards for the pharmaceutical sector. This ensures accurate information is provided to customers regarding product shelf life, improving transparency and compliance. The change impacts the Point of Sale, Sale Stock, and Stock Account modules.
Original PR description
It's common in pharmaceutical industry to provide expiration dates of lots on customer invoices. Because of that, the lot expiration date is now added to `_get_invoiced_lot_values()`, together with lot properties. Task: 4985878 Related: https://github.com/odoo/enterprise/pull/103649 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
This update simplifies the process of using the 'Purchase Alternative' feature by moving it into a separate module. Previously, it was hidden within the purchase requisition process, making it difficult to find. Now, users can directly enable this feature from the Purchase settings, improving usability and streamlining workflows.
Original PR description
*: purchase_requisition ----------------------------------------------------------------------------------------- We have separated the `Purchase Alternative` functionality from the `purchase_requisition` module and created a new independent module called `purchase_alternative`. A new Boolean field, Purchase Alternative, has been added in Purchase settings to manage this feature. Previously, the `Purchase Alternative` option was hard to find; It only appeared after enabling Purchase Agreements, saving, and refreshing the Purchase settings view. This was very confusing and difficult to find for the user Now, users can directly enable the `Purchase Alternative` feature from the Purchase settings without relying on the `purchase_requisition` module. This makes the feature easier to access and more modular. taskId :- 4737059
Enhancements to existing features
This update streamlines the process of canceling NFC-e receipts generated from Point of Sale orders. Previously, users had to manually handle cancellations through the SEFAZ portal, which was time-consuming. Now, a new button within the back-end allows for direct cancellation, improving efficiency and reducing manual effort.
Original PR description
With this **PR**, NFC-e generated from PoS orders can now be canceled directly from the back-end. Previously, users were required to manually perform the cancellation through the SEFAZ portal, which was cumbersome. A new button is added on the PoS order form to trigger the NFC-e cancellation. Upon successful cancellation, the related XML is saved and attached to the chatter. If an error occurs, a user-friendly message is displayed showing the relevant error code and description returned by SEFAZ/Avalara. **task**-5254905
This update ensures that withholding taxes are correctly reflected when uploading vendor bills from electronic invoices in Colombia. Previously, the system didn't recognize withholding taxes in XML files, leading to inaccurate bill uploads. Now, the XML parser accurately captures and includes these taxes, improving data accuracy for Colombian accounting.
Original PR description
Purpose: For Colombia, it is possible to upload vendor bills by drag and dropping the electronic invoice XML into the purchase journal. The XML file is parsed through for relevant information to create the vendor bill. Since vendor bills in Colombia will typically include withholding taxes, the parser should handle this case for a more accurate bill upload. Current Behavior: When uploading XML files that includes withholding taxes, the withholding taxes are not reflected on the uploaded vendor bill. Expected Behavior: When uploading XML files that includes withholding taxes, the withholding taxes are reflected on the uploaded vendor bill. task-5255094
This update makes the HR Applicant data available for use in other Odoo modules. Previously, this data was isolated. This change improves data flow and allows for more integrated HR processes within the system.
Original PR description
Export HrApplicant model so that it can be used in other modules Task-[5461729](https://www.odoo.com/odoo/5778/tasks/5461729) Enterprise PR odoo/enterprise#103402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243317
This update adds three new fields to Odoo invoice PDFs – Buyer Reference, Contract Reference, and Purchase Order Reference – to comply with Chorus Pro requirements. These fields allow users to accurately document key purchase information directly on the invoice, streamlining the accounting process for Chorus Pro transactions.
Original PR description
This commit: - Add three reference fields to invoice PDF for Chorus Pro compliance: Buyer Reference, Contract Reference, and Purchase Order Reference. These fields appear in the invoice header when set on the invoice. task-5410836 Forward-Port-Of: odoo/odoo#240494
This commit updates the o_spreadsheet component with new styling options for pivot tables, enhancing their visual appearance and functionality. The changes allow for more flexible and dynamic styling of pivot tables directly within formulas, improving the user experience for data analysis. This improves the presentation and usability of pivot tables.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/e5cbf1807 [REL] 19.2.0-alpha.3 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits:
https://github.com/odoo/o-spreadsheet/commit/e5cbf1807 [REL] 19.2.0-alpha.3 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
https://github.com/odoo/o-spreadsheet/commit/c206f46b4 [FIX] Pivots: Recompute measure on indirect dependency update [Task: 5349782](https://www.odoo.com/odoo/2328/tasks/5349782)
https://github.com/odoo/o-spreadsheet/commit/c1c00f4d9 [IMP] pivots: implement pivot table styles [Task: 4552232](https://www.odoo.com/odoo/2328/tasks/4552232)
https://github.com/odoo/o-spreadsheet/commit/fcdef4757 [IMP] renderer: draw cell background over grid lines [Task: 4552232](https://www.odoo.com/odoo/2328/tasks/4552232)
https://github.com/odoo/o-spreadsheet/commit/a865dbf2c [IMP] style: add `skipCellGridLines` style option [Task: 4552232](https://www.odoo.com/odoo/2328/tasks/4552232)
https://github.com/odoo/o-spreadsheet/commit/86856abfd [REF] table style: add `bold` to table style presets [Task: 4552232](https://www.odoo.com/odoo/2328/tasks/4552232)
https://github.com/odoo/o-spreadsheet/commit/351919f8f [REF] subtotal: extract SUBTOTAL tracking to generic plugin [Task: 4552232](https://www.odoo.com/odoo/2328/tasks/4552232)
https://github.com/odoo/o-spreadsheet/commit/4dee81dbe [IMP] Added some shortcuts [Task: 5231802](https://www.odoo.com/odoo/2328/tasks/5231802)
https://github.com/odoo/o-spreadsheet/commit/c7180d1f7 [FIX] tests: fix useless shortcuts tests [](https://www.odoo.com/odoo/2328/tasks/)
https://github.com/odoo/o-spreadsheet/commit/a30272f1f [IMP] Autocompletion of curly brackets {} [](https://www.odoo.com/odoo/2328/tasks/)
https://github.com/odoo/o-spreadsheet/commit/21e3d6155 [FIX] f&r: the searched range should follow the active sheet [Task: 5423885](https://www.odoo.com/odoo/2328/tasks/5423885)
https://github.com/odoo/o-spreadsheet/commit/20ee28aac [IMP] figure: add data-type attribute to figure carousel tabs [Task: 5447027](https://www.odoo.com/odoo/2328/tasks/5447027)
https://github.com/odoo/o-spreadsheet/commit/abb24152c [FIX] Style: UPDATE_CELL overwrites the cell style [Task: 5441149](https://www.odoo.com/odoo/2328/tasks/5441149)
https://github.com/odoo/o-spreadsheet/commit/a4792e26f [FIX] tests: fix network serialization in mock [Task: 5441149](https://www.odoo.com/odoo/2328/tasks/5441149)
https://github.com/odoo/o-spreadsheet/commit/ea607f07d [IMP] formulas: add spilled range operator [Task: 5365642](https://www.odoo.com/odoo/2328/tasks/5365642)
https://github.com/odoo/o-spreadsheet/commit/3b6e45921 [IMP] style: check if default but faster [Task: 5431688](https://www.odoo.com/odoo/2328/tasks/5431688)
https://github.com/odoo/o-spreadsheet/commit/abeea3e5d [FIX] Composer: Capture the correct selection on `F2` [Task: 5462713](https://www.odoo.com/odoo/2328/tasks/5462713)
https://github.com/odoo/o-spreadsheet/commit/7c556a916 [REF] lint: enforce braces for all control statements [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)
Co-authored-by: Florian Damhaut (flda) <flda@odoo.com>
Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com>
Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com>
Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com>
Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com>
Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com>
Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com>
Co-authored-by: Rémi Rahir (rar) <rar@odoo.com>
Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com>
Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>This update simplifies pivot table styling within the Odoo Enterprise spreadsheet tool. Users no longer need to manually create tables to apply styles; new styles are directly linked to the pivot, offering greater flexibility and control over formatting and presentation.
Original PR description
With this commit, we don't need to manually create a dynamic table to a pivot to have a style applied. Instead we can add a style in the pivot definition, and dynamic tables will automatically be created on the dynamic pivot formulas. Those new pivot styles are better than traditional tables styles because: - they are directly linked to the pivot, taking into account the number of headers, the presence of totals, etc. - they are automatically added on `=PIVOT()` formulas, without the need to create a dynamic table first. - they are more powerful than the old table styles, they can have a style for the sub-headers, the measure headers, etc. Task: 4552232
This update reflects a recent change in the daily UMA (Wage Contribution) value mandated by INEGI for Mexico, effective February 1st, 2026. The new value of 117.31 MXN has been incorporated into the payroll calculations for Mexican employees, ensuring compliance with current regulations. This change impacts payroll processing for the 19.0 release.
Original PR description
As per the INEGI press release (published on January 8, 2026), the daily UMA value has been updated for 2026. New value: 117.31 MXN Effective date: February 1st, 2026. This commit adds this new parameter value to "Mexico: Daily UMA". Reference: https://www.inegi.org.mx/app/saladeprensa/noticia/10533 target: 19.0 task-5488243 Forward-Port-Of: odoo/enterprise#104064
Resolved issues and error corrections
This update resolves an issue where credit notes with discounts were being rejected by SUNAT. The fix prevents users from creating credit or debit notes with line discounts, aligning with SUNAT regulations that treat credit notes as pure amount adjustments. This ensures proper EDI validation and processing of credit notes in Peru.
Original PR description
Steps to reproduce: - With a PE Company setup - Create an Invoice with "Document Type" set to "(01) Factura" - Set a discount on the invoice line - Confirm and send for validation - Create the credit…
Steps to reproduce: - With a PE Company setup - Create an Invoice with "Document Type" set to "(01) Factura" - Set a discount on the invoice line - Confirm and send for validation - Create the credit note - Confirm the credit note and send for validation Issue: Credit note validation will fail with error `3271|El valor de venta por ítem difiere de los importes consignados. - Detalle: xxx.xxx.xxx value='ticket: 1767185167086 error: Error en la linea: 1: 3271 (nodo: "cac:CreditNoteLine/cbc:LineExtensionAmount" valor: "600.00")'` This occurs because while UBL standard allows AllowanceCharge in credit notes, SUNAT does not. Credit notes are treated as pure amount adjustments, not price recalculations. Discounts were already applied in the invoice, so SUNAT ignores AllowanceCharge in CN, causing error 3271. With this commit we introduce a check to ensure users won't post edi credit or debit notes containing line discounts opw-5414766 Forward-Port-Of: odoo/enterprise#103106
This update resolves a security issue where users could access softphone features (creating or viewing tickets/applicants) without the necessary permissions. The fix adds crucial permission checks to the softphone interface, ensuring only authorized users can perform these actions. This improves security and prevents unauthorized access to sensitive functionality.
Original PR description
The ticket/applicant create/view buttons on softphone are missing permission check. Add them. Task-5461729 Forward-Port-Of: odoo/enterprise#103402
This update resolves an issue where payment processing could fail due to unexpected text responses from providers like Flutterwave and Worldline during outages. The system now gracefully handles these responses, preventing errors and ensuring smoother payment processing. This improves the reliability of our payment integrations.
Original PR description
Both Flutterwave and Worldline may respond with plain text rather than JSON-formatted responses when a Cloudflare outage occurs. This would lead to a traceback in Odoo when trying to extract the error message from the request response. This commit introduces a fallback to the text content of the response when any provider fails to parse the response as a JSON content. opw-5403982 Forward-Port-Of: odoo/odoo#242894
The issue was caused by an inefficient domain optimization during a calculation involving deferred revenue. The optimized domain resulted in a large number of records being evaluated, leading to a memory exhaustion (MemoryError). This fix improves the domain optimization process to reduce the number of records processed, preventing the memory issue.
Original PR description
**Description:** - The [Invoices To Be Issued and Invoiced Not Delivered](https://github.com/odoo/enterprise/blob/19.0/sale_account_accountant/views/sale_order_line_views.xml#L73-L91)…
**Description:**
- The [Invoices To Be Issued and Invoiced Not Delivered](https://github.com/odoo/enterprise/blob/19.0/sale_account_accountant/views/sale_order_line_views.xml#L73-L91)
ir.actions.act_window menus from the sale_account_accountant module were triggering MemoryError on databases with millions of sale.order.line records. These actions call [_search_invoice_to_be_issued and _search_deferred_revenue](https://github.com/odoo/enterprise/blob/master/sale_account_accountant/models/sale_order_line.py#L17-L29)
which iterate over all lines and access the non-stored computed fields [qty_delivered_at_date](https://github.com/odoo/odoo/blob/master/addons/sale/models/sale_order_line.py#L905) and [qty_invoiced_at_date](https://github.com/odoo/odoo/blob/master/addons/sale/models/sale_order_line.py#L985).
- On similar lines, two additional menus—[Bill To Receive and Billed Not Received](https://github.com/odoo/enterprise/blob/19.0/purchase_accountant/views/purchase_order_line_views.xml#L61-L78)
were introduced from the purchase_accountant module. These menus were also triggering MemoryError on databases with a large number of purchase.order.line records. These actions call [_search_prepaid_expense and _search_bill_to_receive](https://github.com/odoo/enterprise/blob/19.0/purchase_accountant/models/purchase_order_line.py#L17-L29) which iterate over all lines and access the non-stored computed fields [qty_invoiced_at_date](https://github.com/odoo/odoo/blob/19.0/addons/purchase/models/purchase_order_line.py#L180) and [qty_received_at_date](https://github.com/odoo/odoo/blob/19.0/addons/purchase/models/purchase_order_line.py#L234).
- To resolve this, we refined _get_accrual_domain to include only lines within a one-year range, from the given accrual date (or today) back to one year earlier, and used split_every in the accrual searches to process the recordset in chunks.
```
matu_3625797_19.0=> select count(*) from sale_order_line;
count
---------
2228032
(1 row)
matu_3625797_19.0=> select count(*) from purchase_order_line;
count
--------
581637
(1 row)
```
**Traceback1:**
```
2025-12-03 07:02:25,973 9344 ␛[1;31m␛[1;49mERROR␛[0m matu_3306966_19.0 odoo.addons.base.maintenance.migrations.base.testsodoo.upgrade.base.tests.test_mock_crawl: Adding menu ('sale_account_accountant.menu_sale_order_line_accrual_to_bill_action', 1295, 'Accounting > Review > Sales > Invoices To Be Issued', 2690) to the failing menus
Traceback (most recent call last):
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 333, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 346, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 506, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 644, in mock_view_list
return self.mock_view_tree(model, view, fields_list, domain, group_by)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 655, in mock_view_tree
self.mock_web_read_group(model, view, domain, group_by, fields_list, limit_group=5)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 713, in mock_web_read_group
data = model.web_read_group(domain, [groupby], aggregates, limit=limit)["groups"]
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 397, in web_read_group
groups, length = self._formatted_read_group_with_length(
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 465, in _formatted_read_group_with_length
groups = self.formatted_read_group(
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 830, in formatted_read_group
groups = self._read_group(
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 33, in _read_group
return self._read_group_for_accrual(domain, groupby, aggregates, having, offset, limit, order)
File "/home/odoo/src/enterprise/19.0/account_accountant/models/analytic_mixin.py", line 21, in _read_group_for_accrual
return super()._read_group(domain, groupby, aggregates, having, offset, limit, order)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 1904, in _read_group
query = self._search(domain)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 5361, in _search
domain = domain.optimize_full(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 445, in optimize_full
return self._optimize(model, OptimizationLevel.FULL)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 653, in _optimize_step
children = self._flatten(child._optimize(model, level) for child in self.children)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 608, in _flatten
for child in children:
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 653, in <genexpr>
children = self._flatten(child._optimize(model, level) for child in self.children)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 957, in _optimize_step
domain = self._optimize_field_search_method(model)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 1016, in _optimize_field_search_method
return Domain.OR(Domain(field.determine_domain(model, '=', v), internal=True) for v in value)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 309, in OR
return DomainOr.apply(Domain(item) for item in items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 595, in apply
children = cls._flatten(items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 608, in _flatten
for child in children:
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 309, in <genexpr>
return DomainOr.apply(Domain(item) for item in items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 1016, in <genexpr>
return Domain.OR(Domain(field.determine_domain(model, '=', v), internal=True) for v in value)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1921, in determine_domain
return determine(self.search, records, operator, value)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 28, in _search_invoice_to_be_issued
ids = [line.id for line in so_lines if line.qty_invoiced_at_date < line.qty_delivered_at_date]
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 28, in <listcomp>
ids = [line.id for line in so_lines if line.qty_invoiced_at_date < line.qty_delivered_at_date]
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1737, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1908, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/19.0/addons/base_automation/models/base_automation.py", line 907, in _compute_field_value
return _compute_field_value.origin(self, field)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 4949, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/odoo/19.0/addons/sale/models/sale_order_line.py", line 989, in _compute_qty_invoiced_at_date
line.qty_invoiced_at_date = line.qty_invoiced
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1693, in __get__
recs._fetch_field(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3769, in _fetch_field
self.fetch(fnames)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3809, in fetch
fetched = self._fetch_query(query, fields_to_fetch)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3930, in _fetch_query
field._insert_cache(fetched, values)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1600, in _insert_cache
collections.deque(map(field_cache.setdefault, records._ids, values), maxlen=0)
MemoryError
```
**Traceback2:**
```
2025-12-03 07:02:30,098 9344 ␛[1;31m␛[1;49mERROR␛[0m matu_3306966_19.0 odoo.addons.base.maintenance.migrations.base.testsodoo.upgrade.base.tests.test_mock_crawl: Adding menu ('sale_account_accountant.menu_sale_order_line_accrual_deferred_revenues_action', 1296, 'Accounting > Review > Sales > Invoiced Not Delivered', 2691) to the failing menus
Traceback (most recent call last):
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 333, in crawl_menu
self.mock_action(action_vals)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 346, in mock_action
return self.mock_act_window(action)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 506, in mock_act_window
mock_method(model, view, fields_list, domain, group_by)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 644, in mock_view_list
return self.mock_view_tree(model, view, fields_list, domain, group_by)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 655, in mock_view_tree
self.mock_web_read_group(model, view, domain, group_by, fields_list, limit_group=5)
File "/tmp/tmpe9cqlr9_/migrations/base/tests/test_mock_crawl.py", line 713, in mock_web_read_group
data = model.web_read_group(domain, [groupby], aggregates, limit=limit)["groups"]
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 397, in web_read_group
groups, length = self._formatted_read_group_with_length(
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 465, in _formatted_read_group_with_length
groups = self.formatted_read_group(
File "/home/odoo/src/odoo/19.0/addons/web/models/models.py", line 830, in formatted_read_group
groups = self._read_group(
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 33, in _read_group
return self._read_group_for_accrual(domain, groupby, aggregates, having, offset, limit, order)
File "/home/odoo/src/enterprise/19.0/account_accountant/models/analytic_mixin.py", line 21, in _read_group_for_accrual
return super()._read_group(domain, groupby, aggregates, having, offset, limit, order)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 1904, in _read_group
query = self._search(domain)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 5361, in _search
domain = domain.optimize_full(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 445, in optimize_full
return self._optimize(model, OptimizationLevel.FULL)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 653, in _optimize_step
children = self._flatten(child._optimize(model, level) for child in self.children)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 608, in _flatten
for child in children:
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 653, in <genexpr>
children = self._flatten(child._optimize(model, level) for child in self.children)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 459, in _optimize
previous, domain = domain, domain._optimize_step(model, next_level)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 957, in _optimize_step
domain = self._optimize_field_search_method(model)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 1016, in _optimize_field_search_method
return Domain.OR(Domain(field.determine_domain(model, '=', v), internal=True) for v in value)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 309, in OR
return DomainOr.apply(Domain(item) for item in items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 595, in apply
children = cls._flatten(items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 608, in _flatten
for child in children:
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 309, in <genexpr>
return DomainOr.apply(Domain(item) for item in items)
File "/home/odoo/src/odoo/19.0/odoo/orm/domains.py", line 1016, in <genexpr>
return Domain.OR(Domain(field.determine_domain(model, '=', v), internal=True) for v in value)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1921, in determine_domain
return determine(self.search, records, operator, value)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 21, in _search_deferred_revenue
ids = [line.id for line in so_lines if line.qty_invoiced_at_date > line.qty_delivered_at_date]
File "/home/odoo/src/enterprise/19.0/sale_account_accountant/models/sale_order_line.py", line 21, in <listcomp>
ids = [line.id for line in so_lines if line.qty_invoiced_at_date > line.qty_delivered_at_date]
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1737, in __get__
self.compute_value(recs)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1908, in compute_value
records._compute_field_value(self)
File "/home/odoo/src/odoo/19.0/addons/base_automation/models/base_automation.py", line 907, in _compute_field_value
return _compute_field_value.origin(self, field)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 4949, in _compute_field_value
determine(field.compute, self)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 81, in determine
return needle(*args)
File "/home/odoo/src/odoo/19.0/addons/sale/models/sale_order_line.py", line 989, in _compute_qty_invoiced_at_date
line.qty_invoiced_at_date = line.qty_invoiced
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1693, in __get__
recs._fetch_field(self)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3769, in _fetch_field
self.fetch(fnames)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3809, in fetch
fetched = self._fetch_query(query, fields_to_fetch)
File "/home/odoo/src/odoo/19.0/odoo/orm/models.py", line 3930, in _fetch_query
field._insert_cache(fetched, values)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields_textual.py", line 243, in _insert_cache
super()._insert_cache(records, values)
File "/home/odoo/src/odoo/19.0/odoo/orm/fields.py", line 1600, in _insert_cache
collections.deque(map(field_cache.setdefault, records._ids, values), maxlen=0)
MemoryError
```
- opw-5238152, opw-5269996
- upg-3306966, 3444833
Forward-Port-Of: odoo/enterprise#101677This update fixes a bug where purchase orders created from purchase agreements didn't correctly apply taxes set by the parent company. The change ensures that taxes associated with agreements are now accurately reflected on child company purchase orders, improving financial reporting and accuracy. This resolves an issue impacting how taxes are calculated across the Odoo system.
Original PR description
### Issue: In a child company, adding a product from a Purchase Agreement to a Purchase Order does not apply the associated parent company's purchase taxes ### Cause: In the onchange, taxes were filtered by company: ```python taxes_ids = fpos.map_tax(line.product_id.supplier_taxes_id.filtered(lambda tax: tax.company_id == requisition.company_id)).ids ``` This filter fails for taxes belonging to the parent company, so they were not applied on the child company purchase order ### Steps to reproduce: - Create a company branch and switch to it - Enable `Purchase Agreements` in Settings - Create a product with a Purchase Taxes (ex. 15%) - Create a Purchase Agreement for any vendor with this product - Create a RFQ for the vendor and add the agreement - Observe that the tax is not applied opw-5121243 Forward-Port-Of: odoo/odoo#243169 Forward-Port-Of: odoo/odoo#237114
This update corrects a problem with Odoo invoices generated for Danish customers, specifically related to the ‘EndpointID’ scheme. The previous version used an outdated codelist, causing validation errors. This fix ensures invoices comply with the required OIOUBL standards, allowing for proper processing of invoices with the Nemhandel system.
Original PR description
**PROBLEM** Generated OIOUBL files don't pass schematrons validations. **STEP TO REPRODUCE** 1. Install the l10n_dk module. 2. Create a dk partner with an adress, and VAT number (DK12345674 for example, don't forget to add a street number for the DK Company address). 3. Create an invoice for the DK partner, and download the xml. 4. Use this validator https://oioubl.nemhandel.dk/validation (Odoo Peppol IAP validator tests oioubl version 3.0 which is not the version we want to test). **CAUSE** We used [wrong codelist](https://oioubl-demo.nemhandel.dk/oioubl/kodelister/ElectronicAddressSchemeCode-3.0.html) (oiubl3.0) for schemeID instead of the [one we should use](https://oioubl21.oioubl.dk/Codelists/en/urn_oioubl_scheme_endpointid-1.1.html) (oioubl2.1). opw-5379474 Forward-Port-Of: odoo/odoo#243342 Forward-Port-Of: odoo/odoo#240586
This update fixes an issue where the system incorrectly predicted downpayment accounts when a specific setting wasn't defined. The change reverted to using historical database data for predictions, ensuring accurate downpayment account assignments within the sales process. This improves the reliability of invoice generation.
Original PR description
In this pr (https://github.com/odoo/odoo/pull/206494), we changed the way downpayment accounts are set. Before, it was set on product categories, now, it's set on res.settings. But with this change, and unexpected behavior occurs. In case the downpayment account is not set in the setting, we try to predict the account to put, but the prediction is wrong, it's predicting based on the partner, but it should be based on the db history. This commit fix that, and brings back the old prediction. task-5473406 Forward-Port-Of: odoo/odoo#243357 Forward-Port-Of: odoo/odoo#242772
This update fixes a problem where customers on one website could access payment providers enabled only for a different website. The fix ensures that payment providers are correctly filtered based on the customer's website, preventing incorrect payment options from appearing in the sales portal. This improves the customer experience and ensures accurate payment processing.
Original PR description
[FIX] website_sale, adding website_id in portal controller Version: 17.0+e Steps to reproduce ------------------ The database has two different websites. A payment provider is enabled for just one of…
[FIX] website_sale, adding website_id in portal controller Version: 17.0+e Steps to reproduce ------------------ The database has two different websites. A payment provider is enabled for just one of them (website1). When a sale order is created on the sales app and the customer accesses it in its portal on the website2, he is able to pay with the payment provider which is only enabled on website1. The problem also occurs when previewing the customer’s portal view. Why it's happening ------------------ When accessing an order via “/my/orders/<int:order\_id>”, the portal_order_page method calls _get_compatible_providers without passing the website_id. The overriding logic in website_payment then defaults to considering all activated payment methods as compatible, regardless of website restrictions. As no website_id is provided, the overriding method from the payment_provider extension in website_payment module considers every activated payment methods as compatible. The Fix ------- We now add the current website's id to the method if none has been added before. opw-5172444, “Payment provider visible on sales order portal" --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243341 Forward-Port-Of: odoo/odoo#235954
This update resolves issues related to leave scheduling changes, specifically preventing leave refusals and handling multi-day leaves more effectively. Now, changes to working schedules before a leave's end split the leave into two records, ensuring accurate duration calculations and excluding cancelled leaves from the process.
Original PR description
Before this commit: - Changing the working schedule the day before a non-refused leave caused the leave to be refused. - For multi-day leaves, changing the working schedule before the end, split the…
Before this commit: - Changing the working schedule the day before a non-refused leave caused the leave to be refused. - For multi-day leaves, changing the working schedule before the end, split the leave into two records, both kept in the same state. - Changing the working schedule while a cancelled leave existed raised an error. After this commit: - Changing the working schedule the day before a leave now resets the leave to draft and recomputes its duration. - For multi-day leaves, changing the working schedule before the end splits the leave into two leaves: - the first keeps its original state, - the second is set to draft. - Cancelled leaves are excluded from the working schedule change flow. task-5420417 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#243451 Forward-Port-Of: odoo/odoo#240408
This update corrects a discrepancy in how tax information is reported for Brazilian invoices impacted by a recent fiscal reform. Previously, tax details were optional, but now they are always required for XML reporting, ensuring compliance. This change impacts the accuracy of tax data for Brazilian businesses using Odoo Enterprise.
Original PR description
Before the fiscal reform, we deliberately avoid sending back informative taxes for service invoices because they may change depending on how and when the invoice is paid and they only need to appear on the XML optionally. New informative taxes specific to the fiscal reform are required to appear on the XML and therefore we must always send them. task-5450142 Forward-Port-Of: odoo/enterprise#103762 Forward-Port-Of: odoo/enterprise#103599
This update fixes an issue where Manufacturing Orders weren't being created correctly when using the Barcode app. Specifically, disabling tracking caused a technical error that prevented components from being added to the order. The fix ensures the correct flow is followed, resolving this problem and improving the reliability of the manufacturing process.
Original PR description
Fix an incorrect flow when creating a Manufacturing Order through the Barcode app. Steps to reproduce: - Disable tracking in Settings - Create a BOM for product Table with components Wood and Screws…
Fix an incorrect flow when creating a Manufacturing Order through the Barcode app. Steps to reproduce: - Disable tracking in Settings - Create a BOM for product Table with components Wood and Screws - In the Barcode app, go to Manufacturing - Click New > Add product and select Table - Click Confirm -> Components are not added after the Table line The issue occurs because `set_qty_producing` is called even when `lot_producing_id` is undefined, leading to a call to `_set_quantity_done` who will delete Stock Move Line since quantity done is 0. So, since SML was deleted, the `move_raw_line_ids` will also be affected. This happens when tracking is disabled, causing the condition `lineRecord.data.lot_producing_id != this.env.model.record.lot_producing_id` to evaluate as true (undefined != false), which triggers `set_qty_producing`. This fix ensures that `lot_producing_id` is defined before performing the comparison. opw-5165163 Forward-Port-Of: odoo/enterprise#104023 Forward-Port-Of: odoo/enterprise#98440
This update resolves an issue where saving electronic invoicing settings on branch companies with identical VAT and Codice Fiscale to their parent company would fail. The fix ensures the correct company (parent) is used when searching for proxy users, preventing errors and improving the reliability of the IT EDI process. This ensures accurate electronic invoicing setup.
Original PR description
Fix issue when saving a branch company sharing the same VAT and Codice Fiscale as its parent. The proxy user search fails because `account_edi_proxy_client.user` is looked up in the branch company instead of the parent one. The same applies when searching the demo user to remove. Steps to reproduce: - Install `account` and `l10n_it_edi` - Set up the company's VAT and Codice Fiscale - Create a branch company with the same VAT and Codice Fiscale - Enable the Electronic Invoicing processing through the SDI in the settings - Select only the branch company and try to save the settings - Observe error since we will try to create a proxy user on the IAP server for an already existing company (the parent one). Ticket [link](https://www.odoo.com/odoo/project.task/5391668) opw-5391668 Forward-Port-Of: odoo/odoo#241443
This update fixes a bug where changes made within the website builder preview were not being saved correctly. The preview was automatically reverted upon user input, leading to lost edits. This ensures that edits made while previewing are preserved, improving the user experience when customizing website elements.
Original PR description
Forward-Port-Of: odoo/odoo#243039
This update enhances the security of survey links by preventing unauthorized access when an applicant is no longer in the hiring process (hired, deleted, etc.). It also ensures that new invite links are always generated, improving the user experience. This resolves an issue where logged-in users could access surveys with valid tokens.
Original PR description
[IMP] hr_recruitment_survey: expire survey links There is no need to be able to access survey links when the applicant is hired, deleted, archived or refused. To do so, a new "cancelled" state had to be added to the survey model (survey.user.input), and I used this state to mark the surveys when doing the aforementioned actions on the applicant. I made so that a new invite would be always regenerated / sent when sending it via the wizard, to avoid confusion with the same invite being resent sometimes. Survey links would always refuse logged in users that were not the intended recipient, even if the answer token was correct. Although opening the url in a private window would allow us to access the survey. This commit fixes that, allowing anyone to access the survey IF the answer_token is valid in the URL. task-4784231
This update optimizes how the Point of Sale system retrieves related data, like product pricing. Previously, searching for product information was slow, especially with a large number of products. Now, the system uses a faster indexing method, resulting in quicker searches and a smoother user experience.
Original PR description
Before this commit, computing a back link (e.g., finding all pricelist items for a specific product template) required iterating over the entire collection of related records for every single record that accessed the property. In a POS with 1,000 products and 10,000 pricelist items, this resulted in $O(N \times M)$ complexity, causing noticeable UI lag during initialization or search. This commit introduces an indexed approach using a reactive effect. The first time a back link is accessed, an inverted index (Map) is built for the entire relation. Subsequent accesses by any record instance become a simple $O(1)$ Map lookup. opw-5448113 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#241783
This update resolves a bug that occurred when switching accounting contexts (COAs) within the Hair Salon Point of Sale (POS) industry. The fix ensures that payment methods are correctly deleted during the CoA switch, preventing database errors and ensuring smooth operation. This improves stability and prevents data inconsistencies.
Original PR description
Steps to reproduce: - Install industry Hair Salon - Settings > Invoicing > Fiscal Localization - Switch to Jordan fiscal localization Issue: Action will fail with error ``` ERROR: update or delete on table "account_journal" violates foreign key constraint "pos_payment_method_journal_id_fkey" on table "pos_payment_method" DETAIL: Key (id)=(6) is still referenced from table "pos_payment_method". ``` Analysis: It occurs because, when switching CoA, the system attempt to delete and re-create journals. However, the hair salon industry initialize a PoS configuration that will create a default payment method based on one of those journal, thus the system will raise a constraint error on delete. A solution is to manually enforce cascade delete when we are switching CoA. opw-5145235 Forward-Port-Of: odoo/odoo#243381 Forward-Port-Of: odoo/odoo#239433
This update ensures that only administrator users can override the maximum closing difference setting when closing a point-of-sale transaction. Previously, users could override this setting regardless of their role, creating potential discrepancies. This change enhances data integrity and control over financial reporting within the POS system.
Original PR description
Currently, the behavior of the "Maximum closing difference" feature with employees depends on the user connected in the backend and not the employee using the pos. Steps to reproduce:…
Currently, the behavior of the "Maximum closing difference" feature with employees depends on the user connected in the backend and not the employee using the pos. Steps to reproduce: ------------------- * Set max closing difference as 0 * Have 1 admin user and 1 pos user * Have 2 employees * Set admin user and employee 1 as advanced employees of the pos * Set pos user and employee 2 as basic employees Steps with admin: * Make sure you are logged as the admin in the database * Open pos (could be a session opened by other user) * Log in with Admin user * Try to close the pos with a difference of 10 -> You can, ok * Log in with employee 1 (advanced) * Try to close the pos with a difference of 10 -> You ca but shouldn't Steps with pos user * Now log in the database as pos user * Open pos (could be a session opened by other user * Log in with employee 1 (advanced) * Try to close the pos with a difference of 10 -> You cannot, ok * Log in with Admin user * Try to close the pos with a difference of 10 -> you cannot but should Why the fix: ------------ Employees that have no linked user should not ba able to override the max difference. Employees who have a connected user should only be able to override the max difference if their user is admin of the pos. opw-5184041 Forward-Port-Of: odoo/odoo#241151 Forward-Port-Of: odoo/odoo#235356
This update fixes an issue where the payment register defaulted to the company bank account instead of the employee's bank account when processing reimbursements. The change re-enabled prioritization of the employee's account, ensuring accurate reimbursement processing. This improves the efficiency and accuracy of employee expense payments.
Original PR description
**Steps to reproduce:** * Create an **employee** with a bank account. * Link the employee’s contact to the current company as a **child partner**. * Create an expense for that employee with payment mode **Paid by Employee**. * Submit, approve, and post the expense. * Open the **payment register** to reimburse the employee. **Observed behavior:** * The payment register defaults to the **company bank account** instead of the employee’s bank account. **Cause:** * The `account_payment_registered` file was removed in this commit: https://github.com/odoo/odoo/commit/704a5a19499469e5a14461bb81d33c832ce00d70#diff-f8829ed273c0ec8838636b1709ac4f895857992dddada6dbcbca3c62a2cbce81 * As a result, the payment register no longer prioritizes the employee’s bank account when the employee contact is linked to the company. **Fix:** * Added `account_register_payment` back to the `__init__` file. opw-5414133 Forward-Port-Of: odoo/odoo#242817
This update fixes an issue where loyalty programs with pricelist restrictions weren't properly recognized in the POS. Previously, a loyalty program could be applied even if the current transaction's pricing didn't match the program's rules. Now, the POS correctly considers pricelist restrictions when determining applicable loyalty programs, ensuring accurate pricing and program application.
Original PR description
Before this commit, if a loyalty program had pricelist restrictions, the POS would not consider them when loading the applicable loyalty programs. This could lead to scenarios where a loyalty program was applied in a POS session even if the session's pricelist was not allowed by the program. This happened when the pricelist was also not available in the POS configuration and program.pricelist_ids was empty. opw-5467990 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#242279
This update resolves a bug where clients were incorrectly using outdated number ranges when syncing data with DIAN. The fix ensures that the latest available number range from DIAN is always used, preventing errors when requesting new ranges. This improves data accuracy and avoids invoice processing issues.
Original PR description
**PROBLEM** When a client has exhausted a number range for a prefix, if he request a new one, when trying to sync the DIAN data the old range will be use instead of the new one. **STEP TO REPRODUCE**…
**PROBLEM** When a client has exhausted a number range for a prefix, if he request a new one, when trying to sync the DIAN data the old range will be use instead of the new one. **STEP TO REPRODUCE** According to the DIAN documentation, the GetNumberRange service is only available in the production environment. So i'm not sure if we can safely test this. The repro steps would be something like: 1. Request a range. 2. Exhaust all number from this range by sending invoices to DIAN. 3. Request a new range. 4. sync with DIAN. (notice the range selected is still the old one). 5. Try sending a new invoice to DIAN and notice there is an error. **CAUSE** In `l10n_co_dian/models/account_journal.py` the function `_l10n_co_dian_get_journal_values()` loops on all the xml `NumberRangeResponse` node and store the last range values encountered for each prefix. We don't check if the this last range is still valid, if it's the newest created (could be checked with the xml field `ResolutionDate`, but the date could be the same if the range were created the same day), if it's the latest in term of number range (DIAN start with range 1-100, then 101-something etc.). Forward-Port-Of: odoo/enterprise#103943
This update resolves inconsistencies in call tracking across multiple browser tabs, ensuring a single, accurate call record is maintained. By streamlining call creation and state validation, the system now handles concurrent users and tab interactions more reliably, preventing issues like calls being marked as missed.
Original PR description
Previously, when a user had multiple tabs open and received a call, each tab created its own call record in the database and managed the call state independently. This led to inconsistencies: for…
Previously, when a user had multiple tabs open and received a call, each tab created its own call record in the database and managed the call state independently. This led to inconsistencies: for example, with two tabs open, accepting a call in one tab would create two call records—one marked as ongoing and the other as missed. This change fixes these issues and addresses several related concurrency and call state management problems. ### Key changes - **Single call creation per incoming call** On an incoming call, only one call record is created. The Call-ID from the SIP INVITE is now used to coordinate and ensure a single call is created in the database. - **Improved handling of concurrent tabs** Each tab still manages the call state from its own perspective, but it now uses the Reason header from SIP CANCEL requests (when present) to avoid marking a call as missed if it was answered in another tab (see “Heterogeneous Error Response Forking Problem” on the web). - **Server-side call state validation** Call state transitions are now validated server-side, allowing proper reconciliation of the different “points of view” coming from multiple tabs. ### Refactoring and architectural improvements - The Session class is now solely responsible for managing the SIP session (as defined in SIP.js). SIP sessions should no longer be accessed directly from outside this class. - Call creation and call state management can now fail without preventing communication. As a result, many components now rely on information from the session rather than the call object (with partner_id remaining on the call). - Active, main, and transfer session changes are now handled by UserAgent and applied immediately when the session state changes. We no longer wait for a call state update to trigger these changes. **Notes** - The Session class could not extend Reactive due to failing SIP.js tests caused by object reference issues. Instead, an event bus is used to notify core VoIP components of session changes. - This work prepares the system for server-side call handling without tab interference (Task 4917399). - When a tab attempts to update a call state, the operation may succeed or fail. In all cases, the server returns the current call state, which may be temporarily inaccurate due to concurrent updates. As a result, a tab’s local view of the call state may be transiently incorrect. task-2810301 Co-authored-by: Bruno Boi <boi@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com>
This update resolves a validation error that occurred when starting work orders with flexible resources, particularly when the time of day was set to a late hour. The fix ensures that attendance intervals are correctly aligned, preventing the 'start date' from being after the 'end date' and ensuring accurate time off calculations.
Original PR description
**Steps to reproduce** On a local DB, with demo data: - Change your machine's time to a late part of the day (e.g. 6pm) - Install `mrp_workorder` - Set the "Standard 40 hours/week" (used by a…
**Steps to reproduce** On a local DB, with demo data: - Change your machine's time to a late part of the day (e.g. 6pm) - Install `mrp_workorder` - Set the "Standard 40 hours/week" (used by a workcenter) as flexible. - From the Shop Floor, start the "WH/MO/00003 - Manual Assembly" workorder. "Validation Error: The start date of the time off must be earlier than the end date." **Cause** `_calculate_date_finished` in mrp is calling `plan_hours` and under certain conditions with a flexible resource, it is possible for `plan_hours` to return a datetime before the `day_dt` parameter. This happens because for flexible resources, `_attendance_intervals_batch` can return attendance intervals with start or end datetimes outside of the start_dt -> end_dt window. For example, a flexible calendar with 8h/day will return the 8:00->16:00 interval, even if start_dt is later than 8:00. **Change** Don't return attendance intervals outside of the [start_dt, end_dt] interval by shifting them if necessary. opw-5123230 Forward-Port-Of: odoo/odoo#243213 Forward-Port-Of: odoo/odoo#233169
This update fixes a problem where employee expense payments were incorrectly linked to the company bank account instead of the employee's. Now, when an employee submits an expense, the payment will automatically use their linked bank account, ensuring accurate reimbursement processing. This improves the financial reporting and accuracy of employee expense payments.
Original PR description
The aim of this commit is to fix the commercial partner id of the move lines to default to the move's partner commercial partner Steps to reproduce: - Have a bank account setup for the current company - Create an employee for a user, sets its `parent_id` to be the current company and set a bank account on the employee - Create an expense for said employee in `own_account` - Submit -> Pay flow - Bank account on the wizard is the company one, not the employee one After this commit: - Bank account on the wizard is the employee one, we stop pretending to reimburse them and actually give them money task-id: 5420587 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#240963
This update corrects a critical issue with the Odoo Enterprise system's testing environment for Shopee integration. Shopee recently changed their API paths, rendering the existing testing configurations invalid. This fix ensures accurate testing and continued functionality with the Shopee platform.
Original PR description
Shopee has changed the API path and the original testing API paths are no longer valid. Forward-Port-Of: odoo/enterprise#103939
This update corrects a potential issue in how the system locks payroll periods for tax reporting (ELM transmission) in Switzerland. By using a reference date, the system now accurately reflects the period being locked, ensuring correct data transmission to tax authorities. This enhances the reliability of financial reporting.
Original PR description
Forward-Port-Of: odoo/enterprise#104269
This update corrects a calculation error in the FedEx delivery pricing, ensuring that delivery costs accurately reflect the sale order's currency. Previously, the system was using the company's currency instead of the sale order's currency, leading to incorrect pricing. This fix ensures accurate delivery charges are displayed.
Original PR description
Issue ----- When the SO and the company use different currencies, the picking currency is correctly set to the SO's but the amount is still computed using the company's currency. Example: Sale in…
Issue ----- When the SO and the company use different currencies, the picking currency is correctly set to the SO's but the amount is still computed using the company's currency. Example: Sale in EUR, Company in USD and 1.5 EUR = 1 USD rate. Sell for 15 EUR of products => the delivery picking shows 10 EUR Steps to reproduce ----- - Activate EUR currency at 1.5 EUR = 1 USD rate - Setup company in USD - Setup INTL FEDEX delivery method - Create a dummy product with a 10 USD sale price - Create a pricelist using the EUR currency - Create a sale for some INTL client - set pricelist to EUR - add dummy product - add INTL FEDEX shipping - confirm the sale - Confirm the linked delivery > Message in chatter shows a price of 10 EUR instead of 15 EUR Cause ----- The problem is with the `carrier_price` field of `stock.picking`. https://github.com/odoo/odoo/blob/7c443175f563b9b12a7b8f638524f7f625962dc2/addons/stock_delivery/models/stock_picking.py#L21 The value is set by https://github.com/odoo/odoo/blob/7c443175f563b9b12a7b8f638524f7f625962dc2/addons/stock_delivery/models/stock_picking.py#L155 which gets its' value from the response of https://github.com/odoo/enterprise/blob/0aea72c8db3067073afe1f89dfddf2b43d9392e9/delivery_fedex_rest/models/delivery_fedex.py#L157 We then go through https://github.com/odoo/enterprise/blob/0aea72c8db3067073afe1f89dfddf2b43d9392e9/delivery_fedex_rest/models/fedex_request.py#L382 where we call https://github.com/odoo/enterprise/blob/0aea72c8db3067073afe1f89dfddf2b43d9392e9/delivery_fedex_rest/models/fedex_request.py#L484 The problem is that in `_decode_pricing` we take the first line matching the `rateType` with no regard to the currency of the rate https://github.com/odoo/enterprise/blob/0aea72c8db3067073afe1f89dfddf2b43d9392e9/delivery_fedex_rest/models/fedex_request.py#L594-L598 we should also filter to ensure the rate matches the order's specified currency. ----- Ticket: opw-5419724 Forward-Port-Of: odoo/enterprise#103737 Forward-Port-Of: odoo/enterprise#103232
This update resolves an issue where creating specific record rules in the Contacts app would trigger a traceback. The fix clarifies which database table is being referenced within a key query, preventing ambiguous column errors and ensuring the Contacts app functions correctly. This improves overall system stability and reliability.
Original PR description
### Issue: When creating a record rule on moves using partners, a traceback is raised when opening a contact. ### Steps to reproduce: - Install 'account_followup' and 'contacts' - In Settings >…
### Issue:
When creating a record rule on moves using partners, a traceback is raised when opening a contact.
### Steps to reproduce:
- Install 'account_followup' and 'contacts'
- In Settings > Technical > Security > Record Rules create a new rule
- name: Test Rule
- model: Journal Entry
- definition: `[('partner_id.is_company', '!=', True)]`
- Open the Contact app and try to open a contact
- Traceback
### Cause:
The newly created rule is used in the query computed by `_compute_has_moves()`. To do this the tables 'account_move' and 'res_partner' are joined. Then `subselect()` simply adds the select element with the string it is given, resulting in:
```sql
SELECT commercial_partner_id
FROM "account_move"
LEFT JOIN "res_partner"
...
```
But both `account_move` and `res_partner` have a column named "commercial_partner_id" resulting in an ambiguous column reference traceback.
### Solution:
We need to add precision on which table should be used. `subselect()` cannot guess which one should be used. We cannot add the precision in the definition of `field_names` because it is not compatible with the domain used by `_search()`.
So we add `'account_move.'` to the field name before giving it to `subselect()`.
opw-5467608
Forward-Port-Of: odoo/enterprise#103792This update fixes an issue where nested kit purchases were incorrectly valuing components, leading to inflated costs. The change ensures that kit valuations are accurately distributed based on component cost shares, particularly when using AVCO (Average Cost) accounting. It addresses a critical bug impacting purchase order accuracy.
Original PR description
### [FIX] purchase_mrp, mrp: correct BoM Kit valuation with nested kits #### Issue: When purchasing a BoM Kit (50/50) containing others BoM Kits (50/50), cost share was applied at each level (50%…
### [FIX] purchase_mrp, mrp: correct BoM Kit valuation with nested kits
#### Issue:
When purchasing a BoM Kit (50/50) containing others BoM Kits (50/50), cost share was applied at each level (50% instead of 25%), leading to overvaluation (e.g., 200% total instead of 100%)
#### Cause:
`cost_share` was always applied fully during BoM explosion and as a portion of the full price on `_get_unit_price()`
#### Other bug fixed:
Fix `_get_cost_share()` to correctly return 0 when BoM total cost_share already equals 100%
#### Requirement:
AVCO (Average Cost) must be enabled on all components/BoMs
#### Steps to reproduce:
1. Recreate that hierarchy with AVCO Products
- A kit "Testing Kit Complete" containing:
-- "Component01", cost share 50%
-- A kit "Testing Kit 1", cost share 50%:
--- "Component02", cost share 50%
--- "Component03", cost share 50%
2. Create and validate a Purchase Order for "Testing Kit Complete" (unit price: 1000)
3. Receive the products
4. Go in Inventory > Reporting > Valuation and search for Component
5. All 3 components are set to 500, instead of Component01: 500 / Component02: 250/ Component03: 250
opw-4806023
### [FIX] purchase_mrp: correct BoM valuation with product variants or optional lines
#### Issue:
BoM valuation ignores variant-specific lines and does not skip lines with quantity 0
#### Cause:
The code only checks that the BoM adds up to 100%
But this can cause issues with variants that do not include all products or with optional lines
As a result, the total valuation may be incorrect
#### Steps to reproduce:
1. Recreate a kit hierarchy with AVCO products:
- Kit "Variant Kit" (Variant Color: White and Wood) containing:
-- "Component01", cost share 0%, only for variant White
-- "Component02", cost share 0%
2. Create and confirm a Purchase Order for "Variant Kit" (variant: Wood, unit price: 1000)
3. Receive the products
4. Go to Inventory > Reporting > Valuation and search for the components
5. Only Component02 appears with 500$, so only half of the total value is shown
opw-4806023
opw-5085457
Forward-Port-Of: odoo/odoo#242316
Forward-Port-Of: odoo/odoo#218326This update corrects a display issue where product prices were incorrectly shown as excluding tax, even when tax-included settings were selected in the Point of Sale system. The fix ensures prices are accurately displayed based on the configured tax settings, providing a more consistent and reliable user experience. The change improves clarity and accuracy for sales transactions.
Original PR description
Steps to reproduce ------------------ 1. Set the PoS taxes display to tax-included 2. In PoS, add a product, change its quantity to 2, and change its price too Notice that the new price / unit is shown as price excluded, even though we set the prices to tax-included in the PoS settings. Reason ------ We were using the getter `currencyDisplayPriceUnit` which uses `displayPriceUnit` which always shows the price as `tax_exluded`. Fix --- Now we change `displayPriceUnit` to adapt to the `iface_tax_included` config in PoS. That follows well the convention used for the non-unit price getter, `displayPrice`. For the cases where we want to explicitly use the tax excluded unit price, we have created the getters `displayPriceUnitExcl` and `currencyDisplayPriceUnitExcl` for that, which replaces some usages of the old getters. opw-5405572 Forward-Port-Of: odoo/odoo#240091
This update resolves issues that arose during module uninstallation, specifically related to how the system handles deleting records from database tables. The changes ensure data integrity by adding warnings for potential problems and updating the uninstallation process to align with best practices, preventing inconsistencies when reinstalling modules.
Original PR description
This fixes two overrides of `unlink()` that break when module `mail` is being uninstalled. It also fixes the uninstalling system to comply to the spec of the `ondelete` decorator. ### Add warnings…
This fixes two overrides of `unlink()` that break when module `mail` is being uninstalled.
It also fixes the uninstalling system to comply to the spec of the `ondelete` decorator.
### Add warnings when some model/field could not be deleted
The uninstallation process tries to delete all the records created by the modules being uninstalled. It uses a best-effort strategy, i.e., it skips the records that cannot be deleted, whatever the reason. But some records are very likely to cause problems, namely `ir.model` and `ir.model.fields` records, because skipping them implies not cleaning up their corresponding table's schema.
For instance, if a column is not dropped, reinstalling the corresponding module will possibly cause inconsistencies, because
- the column contains old values for existing records, which won't be recomputed (if the field is computed);
- the column contains NULLs for records created between the uninstallation and the reinstallation of the module.
We therefore add a warning in those cases, in order to detect and fix those potential issues as soon as possible.
### Make ondelete decorator work as documented
A method decorated with `@api.ondelete(at_uninstall=False)` should be called except when the method's module is being uninstalled. Currently the method is skipped when *any* module is uninstalled.
The fix consists in adding the set of modules being uninstalled in the attribute `registry.uninstalling_modules`, which may be used to detect uninstallation and determine which modules are being uninstalled.
### Replace MODULE_UNINSTALL_FLAG by new conventional flag 'force_delete'
We turn constant `MODULE_UNINSTALL_FLAG` into an explicit conventional flag, and rename it `force_delete` for the sake of simplicity. The idea is to decouple the flag from uninstallation. The caller simply uses
```py
records.with_context(force_delete=True).unlink()
```
to bypass some deletion hooks, which typically prevent deletion by raising some exception, in order to avoid data inconsistencies. On the callee's side, one has to explicitly detect the flag and skip the checks, like in:
```py
@api.ondelete(at_uninstall=False)
def _prevent_deleting_confirmed(self):
if self.env.context.get('force_delete'):
return
if any(record.state == 'confirm' for record in self):
raise UserError(_("You cannot delete confirmed records!"))
```
Note that the uninstallation process uses the convention by automatically adding `force_delete=True` in the `context` for deleting records.
### Fix issue module mail uninstallation
Two overrides of `unlink()` on models `ir.model` and `ir.model.fields` fail when uninstalling module "mail", because their code relies on some columns and those columns have been dropped already. This causes some table and column to remain after uninstallation. When reinstalling module "mail", errors like follows are logged:
```
column "mail_message_id" of relation "mail_tracking_value" contains null values
```
The fix consists in turning the overrides in proper "ondelete" methods, which are skipped when module "mail" is uninstalled.
https://github.com/odoo/enterprise/pull/103651
Forward-Port-Of: odoo/odoo#242777This update resolves an issue where module uninstallation could cause data loss. The update ensures that data is properly handled during module removal, preventing potential problems with related data. This improves the overall stability and reliability of the Odoo Enterprise system.
Original PR description
Companion of https://github.com/odoo/odoo/pull/242777 Forward-Port-Of: odoo/enterprise#103651
This update ensures that the wizard automatically closes after a report is downloaded, regardless of whether a custom report handler (like for IoT) is used. Previously, using a custom handler prevented the wizard from closing, leading to unexpected behavior. This fix maintains consistent user experience across all report types.
Original PR description
Problem: When an alternate ir.action.report handler is used (such as for IoT), the logic to close the wizard after the report is downloaded (printed) is skipped, so the wizard stays open. Steps to Reproduce: - Go to "Acoustic Bloc Screens" product and click "Print Labels" - Select "ZPL labels" and confirm - The report downloads and the wizard closes as expected - Go to Settings > Technical > Reports and select "Product Label (ZPL)" - Set an IoT device on the report - "Print Labels" again, selecting a printer and the IoT toasts in the top right appear after the wizard closes - Refresh the page, and try printing again - The wizard stays open (wrong) and the IoT toasts appear Solution: When returning from the custom handler, check if close_on_report_download and close the wizard. opw-5153139 Forward-Port-Of: odoo/odoo#242045 Forward-Port-Of: odoo/odoo#238247
This update corrects a previous navigation enhancement that caused duplicate breadcrumb displays on mobile forums, specifically within course forums. The fix ensures a cleaner, more intuitive user experience by properly scoping the breadcrumb rendering. This improves usability for all users accessing the forum on mobile devices.
Original PR description
This PR fixes an oversight introduces in Commit[^1]. With Commit 1, we improved the navigation by showing the back button everywhere on the forum but this created an issue due to a rule in `website_slides_forum` rendering the whole breadcrumb if the forum is a course one. | saas-19.1 and above | This PR | |--------|--------| | <img width="391" height="205" alt="image" src="https://github.com/user-attachments/assets/385a6d95-d8b4-4693-8c13-457e2b06f2fe" /> | <img width="390" height="145" alt="image" src="https://github.com/user-attachments/assets/429979a9-ed09-4fe7-8ded-e95909a9c97b" /> | [^1]: https://github.com/odoo/odoo/commit/bb5b7cfa284a55e6dd3a5deb4870bcfae28033af task-5490243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243585
Code cleanup and technical improvements
This update enhances how mentions are handled within Odoo's discussion threads. The changes streamline the process of referencing discussions, making it easier for users to collaborate and stay informed. This improves the overall user experience for discussing topics within Odoo.