Daily updates from Odoo
Wednesday, January 14, 2026
183 changes
11 changes
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% from January 1st, 2026, and 15.02% from February 1st, 2026, ensuring 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 payment channels in Thailand (TH), Malaysia (MY), and Vietnam (VN) through Xendit. This expansion allows our business users to accept payments from customers in these key Southeast Asian markets, broadening our reach and payment capabilities.
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
Enhancements to existing features
This update adds three new fields to invoices generated with the l10n_fr_facturx_chorus_pro module: Buyer Reference, Contract Reference, and Purchase Order Reference. These fields are required for Chorus Pro compliance, ensuring invoices meet the necessary documentation standards for accurate financial reporting.
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
Resolved issues and error corrections
This update fixes a problem where Odoo couldn't correctly identify proxy users when a branch company had the same VAT number as its parent. This prevented users from saving electronic invoicing settings. The change ensures the correct company is used for proxy user searches, improving stability and functionality.
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 corrects a problem in the Barcode app for Manufacturing Orders. When tracking is disabled, a Manufacturing Order wasn't correctly created with components. The fix ensures the necessary data is set before comparisons are made, preventing errors and ensuring components are added to the order as expected.
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 user edits within the website builder preview were lost. The system now reverts the preview immediately upon user input, ensuring edits are saved correctly. This improves the user experience and prevents data loss during preview interactions.
Original PR description
Forward-Port-Of: odoo/odoo#243039
This update optimizes how the Point of Sale system searches for related product information, like pricelists. Previously, searching 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 fixes an issue 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 automatically uses their linked bank account, ensuring accurate and timely reimbursements. This improves the financial reporting and streamlines the expense process.
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 resolves a problem that occurred when switching between accounting configurations (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.
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 fixes an issue where the payment register incorrectly defaulted to the company bank account instead of the employee's bank account when processing reimbursements. The change re-enabled prioritization of employee bank accounts, ensuring accurate payment registration for employee expenses. This improves the accuracy of financial reporting.
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 resolves a crash that occurred when using the 'Integer Rounding' option in accounting reports (like Aged Receivable). The issue stemmed from a calculation error when a report column returned a 'None' value. The fix ensures that rounding is skipped when a 'None' value is encountered, preventing the crash and improving report stability.
Original PR description
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to…
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to reproduce: 1) Install 'account_reports' module with demo data and enable developer mode. 2) Navigate to Accounting > Reporting> Partner Reports > Aged Receivable. 3) Click on 'gear icon' to navigate advance options. 4) Click on the Options tab and set Integer Rounding to 'Nearest', click save and close adv options. 5) Expand a partner line. Error: `TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'` Root Cause: When integer rounding is enabled, the system iterates over formula results to round them using `float_round`(see[1]). However, specific report columns (such as totals for empty periods) may return None. The `float_round` function attempts to perform arithmetic on this value, failing because it cannot divide NoneType. FIX: Skip the rounding if the value received at [1] is None. [1]- https://github.com/odoo/enterprise/blob/9b517564d95424836da1e8368f6b5dc52ae45d1a/account_reports/models/account_report.py#L3329 opw-5392883 Forward-Port-Of: odoo/enterprise#102417
11 changes
New functionality added to Odoo
This update adds support for payment channels in Thailand (TH), Malaysia (MY), and Vietnam (VN) through Xendit. This expansion allows Odoo to process payments from these key markets, broadening our customer base and improving payment flexibility.
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#189527
Enhancements to existing features
This update allows system administrators to customize the main Odoo Enterprise home menu with a targeted message. Administrators can set a message via a database configuration, such as a maintenance notice, which will then be displayed to all users. This provides a flexible way to communicate important information directly to users within the system.
Original PR description
Display a message on home menu based on an ir.config_parameter that can be added directly in the database by the system administrator.
The ir.config_parameter is sysadmin.message and should be a json loadable. The format shoud be something like this:
{
"type": "warning",
"replace": false,
"warning_type": "user",
"message": "`<span>A maintenance operation is planned on your server on <strong>2026-01-15</strong> between 14h and 15h</span>`"
}
Forward-Port-Of: odoo/enterprise#103831
Forward-Port-Of: odoo/enterprise#102239Resolved issues and error corrections
This update resolves an issue preventing receipt printing when multiple payment methods were used in the Italian POS (l10n_it_pos) module. The fix backports a change from another Odoo project, ensuring accurate receipt generation for all payment types. This improves the user experience for Italian POS users.
Original PR description
Backports of https://github.com/odoo/enterprise/pull/96353. References: See page 36 in the [official docs](https://download4.epson.biz/sec_pubs/bs/pdf/ePOS%20Fiscal%20Print%20Solution%20Development%20Guide%20Rev%20T.pdf). Ticket [link](https://www.odoo.com/odoo/project.task/5376242) opw-5376242 Forward-Port-Of: odoo/enterprise#103710
This update resolves an issue where Odoo incorrectly searched for proxy users when a branch company had the same VAT/Codice Fiscale as its parent. This prevented users from correctly configuring Electronic Invoicing (IT EDI) for branch offices. The fix ensures the correct company is identified during proxy user searches, improving EDI processing reliability.
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 limitation in the portal's canned response feature, allowing internal users to properly access and utilize available responses. The previous fix was removed and replaced with a more appropriate solution, preparing for future support of the `::` delimiter within the portal. This enhancement ensures a smoother experience for users interacting through the portal.
Original PR description
*: im_livechat, portal, project, test_mail_full PR #192953 introduces a composer action for canned responses. The feature is available in portal for internal users but since `suggestion` is disabled in portal, this feature doesn't work properly. In preparation for supporting `::` delimiter in portal, the incorrect fix in PR #231360 has been reverted. `inFrontendPortalChatter` is specific to portal frontend and should not be set to `true` in the project sharing environment. Instead of the mentioned fix, a similar fix from PR #231441 has been backported. task-5262349 Forward-Port-Of: odoo/odoo#235551
This update ensures that the correct warehouse location is linked when manufacturing merged production orders. Previously, the system incorrectly defaulted to the warehouse's default location, causing issues with multi-location workflows. This fix guarantees accurate tracking of materials throughout the manufacturing process.
Original PR description
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in…
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1054 because of the `m.location_id == move.location_final_id` part being false in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1090-L1097 This is because, during the merge, `location_final_id` is not propagated to the new MO https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L2416-L2424 so when the new MO's `move_finished_id` gets computed https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L822 it gets the MO's `location_final_id` https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L1202 which is false. This leads to to the move getting the warehouse's default stock location thanks to https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/mrp/models/stock_move.py#L456-L457 This is problematic for complex use cases with multi-locations and custom routes. It should be safe to propagate the `location_final_id` of the merged MOs if they all share the same one. Use case example ----- <details> <summary>Full use case</summary> - Enable multi-step routes - Create location "WH/Stock/L1" - Create location "WH/Stock/L2" - Create Operation Type "MO child" - Type of Operation: Manufacturing - Sequence Prefix: MOCHILD - Source Location: L1 - Destination Location: L2 - Create Operation Type "Push Transfer" - Type of Operation: Internal Transfer - Sequence Prefix: L2L1 - Source Location: L2 - Destination Location: L1 - Create Route "MO child" - Create Rule "Manufacture" - Action: Manufacture - Operation Type: MO child - Source Location: False - Destination Location: Stock - Create Route "2-step" - Warehouse: Main WH - Create Rule "L1 -> Virtual/Production" - Action: Pull from - Operation Type: MO child - Source Location: L1 - Destination Location: Virtual/Production - Create Rule "Push: L2 -> L1" - Action: Push To - Operation Type: Push Transfer - Source Location: L2 - Destination Location: L1 - Unarchive MTO - Edit MTO route - Create Rule "L1 -> Virtual/production (MTO)" - Action: Pull - Operation Type: "My Company: Manufacturing" - Source Location: L1 - Destination Location: Virtual/Production - Supply Method: Trigger another rule - Create product "Main product" - Create product "Child product" - Routes: "MO child" & MTO - Create product "Material" (consumable) - Create BOM - Product: "Main product" - Component: "Child product" - Create BOM - Product: "Child product" - Component: "Material" - Create MO for "Main product" - Misc/Component Location set to L1 - Duplicate the MO - Merge child MOs & produce - Validate merged MO transfer to L1 - Go back to one of the "Main product" MO > Component quantity is 0 </details> ----- Ticket: opw-5144196 Forward-Port-Of: odoo/odoo#242373 Forward-Port-Of: odoo/odoo#240695
This update resolves a bug that occurred when switching fiscal localizations (like Jordan) within the Hair Salon industry module. The system was incorrectly attempting to delete and recreate journals, leading to a database error. This fix ensures a proper cascade delete process, preventing the error and maintaining data integrity.
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 corrects a bug where delivery fees weren't accurately calculated when sales orders and company currencies differed. The fix ensures that delivery fees are correctly priced based on the sales order's currency, preventing discrepancies in pricing displayed to customers. This improves financial accuracy and reduces potential billing errors.
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 fixes an issue where components added to manufacturing orders through the product catalog weren't correctly transferred to the pre-production warehouse. The fix adds a warehouse ID to these moves, ensuring proper inventory tracking and fulfilling multi-step manufacturing processes. This improves the accuracy of stock levels and streamlines production workflows.
Original PR description
Issue
-----
In multi step manufacturing, components added to MO through the catalog don't get transfered to the pre-prod location.
Steps to reproduce
-----
- 2 step manufacturing
- Create 2 products
- Create a MO for the first product
- Open the product catalog
- Add some qty of the second product
- Go back to the MO & confirm it
> No procurement transfer for the second product from stock to pre-prod
Cause
-----
The move created by the catalog has no `warehouse_id` so in `adjust_procure_method` we don't find any rule which means it gets set to MTS
https://github.com/odoo/odoo/blob/6ecd271ff34313d900a0ad14b1c20679808ba9b8/addons/stock/models/stock_move.py#L2366-L2368
-----
Ticket:
opw-5221418
Forward-Port-Of: odoo/odoo#243036
Forward-Port-Of: odoo/odoo#239265This update fixes an issue where GS1 barcodes weren't accurately reflecting the quantity of products in manufacturing orders. Previously, the system only recorded a single unit regardless of the barcode's specified quantity. Now, the system correctly uses the barcode quantity to update the product's completed quantity, ensuring consistency and accurate tracking of manufactured goods.
Original PR description
Description of the issue/feature this PR addresses: The quantity of GS1 barcodes was not taken into account when scanning the final product of a manufacturing order. More details of this issue can be found in https://www.odoo.com/odoo/project.task/4817418 Current behavior before PR: When scanning a GS1 barcode with a quantity defined (e.g. 0120250524135700310210000010LOT887766 ) as the final product of a manufacturing order, the quantity is not taken into account in the call to produceQty(), so the line will have a qty_done of 0 regardless of the quantity specified in the barcode Desired behavior after PR is merged: The qty_done of the final product line should be the one specified in the barcode, in order to make the behaviour consistent with other usages of GS1 barcodes. Forward-Port-Of: odoo/enterprise#104024 Forward-Port-Of: odoo/enterprise#95174
This update fixes an issue where loyalty programs with pricelist restrictions weren't consistently applied in the POS. Previously, if a POS session's pricelist didn't match a loyalty program's restrictions, the program wouldn't be applied. Now, loyalty programs with restrictions will correctly filter applicable discounts in the POS, ensuring accurate pricing.
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
18 changes
New functionality added to Odoo
This update expands Odoo's payment capabilities to include Xendit, a popular payment gateway, in Thailand, Malaysia, and Vietnam. The changes add necessary configurations to support local payment channels, enabling businesses to accept payments from customers in these regions.
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#189527
Enhancements to existing features
This update allows branch companies within Odoo to participate in the Peppol network. Users can register their branch as a sender for the parent company or create a new registration, providing greater flexibility for international trade and compliance. This change simplifies the process for businesses operating across multiple locations.
Original PR description
This commit implements the functionality to allow all branch company to use Peppol. With this commit, the user can register a branch company in the peppol network in two ways: - By setting the same EAS/Endpoint than the one set on the parent company, the branch will be registered as a sender for the parent company. - By setting another EAS/Endpoint than the one set on the parent company, the branch will do a new registration. task-4852830 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#240081
This update allows system administrators to customize the main Odoo Enterprise home menu with a targeted message. Administrators can set a message via a configuration parameter, visible to all users. This enables timely communication about planned maintenance or important updates directly within the application.
Original PR description
Display a message on home menu based on an ir.config_parameter that can be added directly in the database by the system administrator.
The ir.config_parameter is sysadmin.message and should be a json loadable. The format shoud be something like this:
{
"type": "warning",
"replace": false,
"warning_type": "user",
"message": "`<span>A maintenance operation is planned on your server on <strong>2026-01-15</strong> between 14h and 15h</span>`"
}
Forward-Port-Of: odoo/enterprise#103831
Forward-Port-Of: odoo/enterprise#102239Resolved issues and error corrections
This update resolves a bug in the General Ledger reporting where analytic group by functionality was producing incorrect results and leading to inaccurate journal entry views. The fix corrects a data ID mismatch, ensuring that the correct journal entries are displayed when grouping by analytic accounts. This improves the accuracy of financial reporting.
Original PR description
Issue: Inconsistent use of line ID in the general ledger between account_move_line.id and account_analytic_line.id Step to reproduce: - Activate analytic accounting - Go to Accounting Report ->…
Issue: Inconsistent use of line ID in the general ledger between account_move_line.id and account_analytic_line.id Step to reproduce: - Activate analytic accounting - Go to Accounting Report -> General Ledger -> Options - Activate "Analytic Group By" - Create an invoice - add a line with an analytic account - Confirm the Invoice - Duplicate the invoice - Confirm the second invoice - Go to the General Ledger - Group By the analytic account you used Current Behavior: General Ledger display 2 lines per journal entry being part of the analytic distribution used for the group by. The first line displays the part related to the analytic group by, while the second line display infos for global general ledger. Clicking on the dots of the first line -> "View Journal Entry" send you to an unrelated entry. Expected behavior: - "View Journal Entry" should send to the right entry Proposed Solution: To proceed to the group_by, `_prepare_lines_for_analytic_groupby` create a temporary SQL table. This table uses the account_analytic_line.id as if it was the account_move_line.id. This commit fixes this and goes back to account_move_line.id. However, lines are merged into only one single line. opw-5267981 Forward-Port-Of: odoo/enterprise#103169
This update resolves an issue where the height of image gallery snippets would unexpectedly reset after changing image order or manually adjusting the height. The fix removes outdated code and ensures the snippet's height remains consistent with the user's input, providing a more reliable and predictable gallery experience. Minor template issues were also addressed.
Original PR description
Steps to reproduce Scenario A 1. Go to Website → drop an Image Gallery snippet → A default height value appears in the `"Height"` input. 2. Select an image → change its order in the carousel → The…
Steps to reproduce Scenario A 1. Go to Website → drop an Image Gallery snippet → A default height value appears in the `"Height"` input. 2. Select an image → change its order in the carousel → The snippet height is automatically reset to `70%` of the screen height. Scenario B 1. Change the height value of the snippet from the `"Height"` option. 2. Select an image → change its order in the carousel → The snippet height is again reset (and the option value is overridden). Issue The original height behavior was introduced in [1] to make the slideshow mode auto-adapt to `70%` of the viewport height. This diff also removed height CSS for other modes where the height should depend on the content [2] Subsequent adaptations: [3] added a default height (`500px`) in XML, [4] removed it during a design refactoring, [5] restored the possibility to control the height of the image gallery snippet using the `"Height"` option. Keeping the same JS logic that forces the snippet height, led to the behavior explained above: even when the user manually sets a height, any action triggering `slideshow()` (e.g., image reorder) forces the height back to 70% of `window.innerHeight`. Fix 1. Remove the outdated JS code that automatically updates the height. 2. Keep the slideshow behavior consistent with [2] by excluding it from the height CSS removal logic. The snippet now starts with a default height and only changes when edited through the `"Height"` input. Additional fixes This commit also fixes a few minor issues in the new carousel items template introduced in [4]: items having an `"undefined"` class, and a missing margin style in the main snippet template. [1]: https://github.com/odoo/odoo/commit/239b6bc0b5a2a644486737f2b0b71e7e6c0a2edf [3]: https://github.com/odoo/odoo/commit/9069d0127c176317436b67b23ae5677dd9d53de7 [4]: https://github.com/odoo/odoo/commit/9042b1cae7b630b20e0670788b7a4ed9e4c97609 [5]: https://github.com/odoo/odoo/commit/d5d138e833344e857a420d865d4b12f1acdb0e7c task-3414281 Forward-Port-Of: odoo/odoo#242385 Forward-Port-Of: odoo/odoo#126766
This update resolves an issue where automated time tracking activities were delayed in creating due to a problem with how the system recomputed dependent fields. Specifically, when a pre-filter condition in an automation rule cleared the compute flag for related fields, the system failed to update them correctly. This resulted in delays, particularly when exceeding allocated time.
Original PR description
This PR is a cherry-pick of: https://github.com/odoo/odoo/pull/236323 When a pre-filter condition of an automation flushes fields, we must ensure that their recomputation is still scheduled…
This PR is a cherry-pick of: https://github.com/odoo/odoo/pull/236323
When a pre-filter condition of an automation flushes fields, we must ensure that their recomputation is still scheduled afterwards For example, if a rule pre-filters on field B (which depends on A), computing A should not clear the compute flag of B
### Issue:
In some automation rules, computed fields must be processed in a specific order (e.g., `effective_hours` -> `remaining_hours`)
However, if `remaining_hours` is referenced in the automation `Before Update Domain`, its compute flag may be incorrectly cleared, preventing the proper recomputation chain
This results in inconsistent behavior, such as delays in activities being created when timesheets exceed allocated time
### Cause:
The automation engine flushes fields referenced in the `Before Update Domain`, but does not restore their compute flags afterward Thus dependent fields are not recomputed as expected
### Steps to reproduce:
1. Enable Debug Mode
2. Create an Automation Rule
-- Name: Time Exceeded
-- Model: Task
-- Trigger: On Save
-- Before Update Domain: [("remaining_hours", ">=", 0)]
-- Apply on: [("remaining_hours", "<", 0)]
4. Create a Project with Timesheets
5. Create a Task inside the Project
6. Set Allocated Time to 10h
7. Use the Start button to record 11h (No activity appears in chatter)
8. Do the same again (Activity appears only after the second exceed) Before the fix, there is always a delay because the recomputation chain is broken
### Tickets:
18.0: opw-4409744
17.0: opw-5237430
Forward-Port-Of: odoo/odoo#243059
Forward-Port-Of: odoo/odoo#239667This update resolves an issue preventing the printing of receipts when multiple payment methods (e.g., cash, credit card) were used in the l10n_it_pos module. The change backports a fix from another Odoo project, ensuring accurate receipt generation for Italian Point of Sale transactions. This improves the user experience and compliance with fiscal requirements.
Original PR description
Backports of https://github.com/odoo/enterprise/pull/96353. References: See page 36 in the [official docs](https://download4.epson.biz/sec_pubs/bs/pdf/ePOS%20Fiscal%20Print%20Solution%20Development%20Guide%20Rev%20T.pdf). Ticket [link](https://www.odoo.com/odoo/project.task/5376242) opw-5376242 Forward-Port-Of: odoo/enterprise#103710
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 resolves an issue where Odoo incorrectly searched for proxy users when a branch company had the same VAT number as its parent. This prevented proper Electronic Invoicing setup for branch companies. The fix ensures the correct company is used for proxy user searches, improving functionality for businesses with multiple entities.
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 limitation in the portal's canned response feature, allowing internal users to properly access and utilize available responses. The previous fix was reverted to ensure correct functionality and prepare for future support of the `::` delimiter in the portal. This enhancement improves the user experience for portal users.
Original PR description
*: im_livechat, portal, project, test_mail_full PR #192953 introduces a composer action for canned responses. The feature is available in portal for internal users but since `suggestion` is disabled in portal, this feature doesn't work properly. In preparation for supporting `::` delimiter in portal, the incorrect fix in PR #231360 has been reverted. `inFrontendPortalChatter` is specific to portal frontend and should not be set to `true` in the project sharing environment. Instead of the mentioned fix, a similar fix from PR #231441 has been backported. task-5262349 Forward-Port-Of: odoo/odoo#235551
This update resolves a bug that occurred when switching fiscal localizations (like Jordan) within the Hair Salon industry module. The fix ensures that payment methods are correctly deleted during the CoA switch, preventing database errors and ensuring smooth operation. This improves stability for users utilizing this specific industry configuration.
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 corrects a bug where delivery fees weren't accurately calculated when sales orders and company currencies differed. The fix ensures that delivery fees are correctly priced based on the sales order's currency, preventing discrepancies in pricing displayed to customers. This improves financial accuracy and reduces potential billing errors.
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 enabling integer rounding in Aged Receivable reports caused a crash. The fix prevents errors when report columns return 'None' values, ensuring the reports function correctly regardless of rounding settings. This improves the stability and usability of the reporting feature.
Original PR description
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to…
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to reproduce: 1) Install 'account_reports' module with demo data and enable developer mode. 2) Navigate to Accounting > Reporting> Partner Reports > Aged Receivable. 3) Click on 'gear icon' to navigate advance options. 4) Click on the Options tab and set Integer Rounding to 'Nearest', click save and close adv options. 5) Expand a partner line. Error: `TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'` Root Cause: When integer rounding is enabled, the system iterates over formula results to round them using `float_round`(see[1]). However, specific report columns (such as totals for empty periods) may return None. The `float_round` function attempts to perform arithmetic on this value, failing because it cannot divide NoneType. FIX: Skip the rounding if the value received at [1] is None. [1]- https://github.com/odoo/enterprise/blob/9b517564d95424836da1e8368f6b5dc52ae45d1a/account_reports/models/account_report.py#L3329 opw-5392883 Forward-Port-Of: odoo/enterprise#102417
This update fixes an issue where components added to manufacturing orders through the product catalog weren't correctly transferred to the pre-production warehouse. The fix adds a warehouse ID to the moves created by the catalog, ensuring proper inventory updates and preventing delays in multi-step production processes. This improves the reliability of component tracking within MRP.
Original PR description
Issue
-----
In multi step manufacturing, components added to MO through the catalog don't get transfered to the pre-prod location.
Steps to reproduce
-----
- 2 step manufacturing
- Create 2 products
- Create a MO for the first product
- Open the product catalog
- Add some qty of the second product
- Go back to the MO & confirm it
> No procurement transfer for the second product from stock to pre-prod
Cause
-----
The move created by the catalog has no `warehouse_id` so in `adjust_procure_method` we don't find any rule which means it gets set to MTS
https://github.com/odoo/odoo/blob/6ecd271ff34313d900a0ad14b1c20679808ba9b8/addons/stock/models/stock_move.py#L2366-L2368
-----
Ticket:
opw-5221418
Forward-Port-Of: odoo/odoo#243036
Forward-Port-Of: odoo/odoo#239265This update ensures that the quantity of products scanned via GS1 barcodes is accurately reflected in manufacturing orders. Previously, the system wasn't properly utilizing the quantity information from the barcode, leading to incorrect production counts. This fix aligns the behavior with other barcode scanning processes, improving data accuracy and order fulfillment.
Original PR description
Description of the issue/feature this PR addresses: The quantity of GS1 barcodes was not taken into account when scanning the final product of a manufacturing order. More details of this issue can be found in https://www.odoo.com/odoo/project.task/4817418 Current behavior before PR: When scanning a GS1 barcode with a quantity defined (e.g. 0120250524135700310210000010LOT887766 ) as the final product of a manufacturing order, the quantity is not taken into account in the call to produceQty(), so the line will have a qty_done of 0 regardless of the quantity specified in the barcode Desired behavior after PR is merged: The qty_done of the final product line should be the one specified in the barcode, in order to make the behaviour consistent with other usages of GS1 barcodes. Forward-Port-Of: odoo/enterprise#104024 Forward-Port-Of: odoo/enterprise#95174
This update fixes an issue where loyalty programs with pricelist restrictions weren't being properly applied in the POS. Previously, if the POS pricelist didn't match a loyalty program's restrictions, the loyalty program would still be applied. Now, the POS correctly considers pricelist restrictions when determining applicable loyalty programs, ensuring accurate pricing at the point of sale.
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 problem where clients were incorrectly using outdated number ranges when syncing data with DIAN. The fix ensures that the latest available number range is always used, preventing errors when sending invoices. This improves data accuracy and avoids disruptions in DIAN compliance.
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 an issue where users could incorrectly save attendance records for employees they weren't authorized to manage. The change now prevents unauthorized write access, ensuring data integrity and preventing potential errors in attendance tracking. Test coverage has been added to confirm this fix.
Original PR description
Closes [odoo/odoo#226007](https://github.com/odoo/odoo/issues/226007). Description of the issue/feature this PR addresses: Prevents a user from updating their attendance record by changing the employee to the one whose attendance is not managed by the current user. Current behavior before PR: - Assign the Officer Group of Attendance group to a user. - Assign the user as the attendance manager of itself. - Login with that user. - Create an attendance record for the employee and save it. - Try to change the employee and save; an error will be thrown as expected. - Go to the Attendance menu; the record will still be saved. Desired behavior after PR is merged: This commit ensures that un-allowed write does not take place + test coverage added. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243573 Forward-Port-Of: odoo/odoo#226335
11 changes
New functionality added to Odoo
This update expands Odoo's payment capabilities to include Xendit, a popular payment gateway, in Thailand, Malaysia, and Vietnam. The changes add the necessary configurations to support local payment channels through Xendit, enabling businesses to accept payments from customers in these regions.
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#189527
Enhancements to existing features
This update adds two new Unit of Measure codes – Minute (MIN) and Kilowatt hour (KWH) – to Odoo, aligning with UNECE Recommendation No.20 for Peppol. Previously, Odoo defaulted to a generic 'Units' code, which wasn't suitable for UBL/CII electronic invoices. This change ensures proper support for these key units, particularly benefiting localization modules like those for Chile and Turkey.
Original PR description
**Issue:** 2 UoM that is in the UNECE Recommendation No.20 for Peppol don't exist in Odoo: - MIN: Minute - KWH: Kilowatt hour Even if they are created manually, they are not used in the UBL/CII electronic invoices. Instead, the default code (i.e. "C62" for "Units" is used). Some localization modules create the "Kilowatt hour" UoM as they need it. (l10n_cl and l10n_tr_nilvera) So it's better to have a "generic" one available for every module. opw-5269119 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243333 Forward-Port-Of: odoo/odoo#238342
Resolved issues and error corrections
This update resolves an issue preventing users in the l10n_it_pos module from printing receipts when multiple payment methods were used. The change backports a fix from another Odoo project, ensuring accurate receipt generation for Italian Point of Sale transactions. This improves the user experience and compliance with fiscal requirements.
Original PR description
Backports of https://github.com/odoo/enterprise/pull/96353. References: See page 36 in the [official docs](https://download4.epson.biz/sec_pubs/bs/pdf/ePOS%20Fiscal%20Print%20Solution%20Development%20Guide%20Rev%20T.pdf). Ticket [link](https://www.odoo.com/odoo/project.task/5376242) opw-5376242 Forward-Port-Of: odoo/enterprise#103710
This update corrects a critical issue with the Odoo Enterprise system's testing environment for Shopee integration. Shopee recently altered their API paths, rendering the previous testing configurations invalid. This fix ensures the testing environment accurately reflects the current Shopee API, maintaining reliable testing and development.
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 resolves an issue where the location of merged manufacturing orders wasn't correctly linked to subsequent transfer orders. The fix ensures that the final location of merged MOs is accurately propagated, preventing incorrect stock movements and improving the reliability of multi-location workflows. This primarily impacts complex manufacturing processes.
Original PR description
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in…
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1054 because of the `m.location_id == move.location_final_id` part being false in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1090-L1097 This is because, during the merge, `location_final_id` is not propagated to the new MO https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L2416-L2424 so when the new MO's `move_finished_id` gets computed https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L822 it gets the MO's `location_final_id` https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L1202 which is false. This leads to to the move getting the warehouse's default stock location thanks to https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/mrp/models/stock_move.py#L456-L457 This is problematic for complex use cases with multi-locations and custom routes. It should be safe to propagate the `location_final_id` of the merged MOs if they all share the same one. Use case example ----- <details> <summary>Full use case</summary> - Enable multi-step routes - Create location "WH/Stock/L1" - Create location "WH/Stock/L2" - Create Operation Type "MO child" - Type of Operation: Manufacturing - Sequence Prefix: MOCHILD - Source Location: L1 - Destination Location: L2 - Create Operation Type "Push Transfer" - Type of Operation: Internal Transfer - Sequence Prefix: L2L1 - Source Location: L2 - Destination Location: L1 - Create Route "MO child" - Create Rule "Manufacture" - Action: Manufacture - Operation Type: MO child - Source Location: False - Destination Location: Stock - Create Route "2-step" - Warehouse: Main WH - Create Rule "L1 -> Virtual/Production" - Action: Pull from - Operation Type: MO child - Source Location: L1 - Destination Location: Virtual/Production - Create Rule "Push: L2 -> L1" - Action: Push To - Operation Type: Push Transfer - Source Location: L2 - Destination Location: L1 - Unarchive MTO - Edit MTO route - Create Rule "L1 -> Virtual/production (MTO)" - Action: Pull - Operation Type: "My Company: Manufacturing" - Source Location: L1 - Destination Location: Virtual/Production - Supply Method: Trigger another rule - Create product "Main product" - Create product "Child product" - Routes: "MO child" & MTO - Create product "Material" (consumable) - Create BOM - Product: "Main product" - Component: "Child product" - Create BOM - Product: "Child product" - Component: "Material" - Create MO for "Main product" - Misc/Component Location set to L1 - Duplicate the MO - Merge child MOs & produce - Validate merged MO transfer to L1 - Go back to one of the "Main product" MO > Component quantity is 0 </details> ----- Ticket: opw-5144196 Forward-Port-Of: odoo/odoo#240695
This update resolves an issue where manually changed currency rates on invoices weren't correctly applied, leading to data loss. The fix now only recalculates rates if the user hasn't modified them, ensuring accurate invoice calculations and preventing data overwrites. This improves the reliability of financial reporting.
Original PR description
in case the user would enter manually a different rate than the default one, but does not fill the invoice date; odoo was setting today as the invoice date, which was changing the rate and recomputing all the lines... Effectively losing everything the user just encoded. So now, we only recompute the rate and the lines if the user didn't change it. Fix: https://github.com/odoo/odoo/pull/226124/changes/1b48d141d7260a262075555c4ab9cedc691d3551 Issue with Fix: Invoices posted on dates different from their creation date do not update their currency rates, even though they should. Comparing `invoice_currency_rate` to the expected rate at creation is a better guess. task-5477481 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#242800
This update resolves an issue where users were blocked from settling customer balances in Point of Sale when ZATCA integration was active. The fix removes the forced invoice requirement for settlement orders, allowing users to complete payments without generating unnecessary e-invoices to ZATCA.
Original PR description
## Dependent PR https://github.com/odoo/enterprise/pull/98463 ## Description of the issue/feature this PR addresses: Users are blocked when trying to use the **Settle Due** feature in Point of Sale…
## Dependent PR https://github.com/odoo/enterprise/pull/98463 ## Description of the issue/feature this PR addresses: Users are blocked when trying to use the **Settle Due** feature in Point of Sale if the ZATCA (l10n_sa_edi_pos) integration is enabled. ## Current behavior before PR: When a PoS order is created using a "Pay Later" payment method, an invoice is correctly generated and sent to ZATCA. However, when the user later tries to settle that customer's due balance (using the **Settle Due** option), the l10n_sa_edi_pos module incorrectly forces the Invoice option to be enabled and makes the field read-only. This blocks the user because: - Settlement orders do not contain any lines, so a new invoice cannot be generated. - The original invoice was already sent to ZATCA, and the settlement payment should not be sent as a new e-invoice. Thus, the user cannot proceed with the settlement. ## Desired behavior after PR is merged: After this fix, the **Invoice** checkbox will no longer be forced or marked as read-only during **Settle Due** operations. The field will default to False, aligning with standard Odoo behavior for settlements and allowing the user to complete the payment. task-5144679 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233769
This update resolves an issue where the 'is_settling_account' flag remained true after a Point of Sale user cancelled a 'Settle Due' payment. This prevented normal sales from being processed correctly, potentially causing errors and bypassing important accounting rules. The fix now ensures the flag is reset to false, allowing for proper order processing.
Original PR description
## Description of the issue/feature this PR addresses: The `is_settling_account` flag on a Point of Sale order is not reset to False if the user cancels a **Settle Due** operation. ## Current…
## Description of the issue/feature this PR addresses: The `is_settling_account` flag on a Point of Sale order is not reset to False if the user cancels a **Settle Due** operation. ## Current behavior before PR: When a user initiates a **Settle Due** payment for a customer, Odoo creates a new order and sets the `is_settling_account` flag to True. If the user proceeds to the payment screen but then navigates back (to the product screen) instead of completing the payment, the flag remains True. This is problematic because the user can then add regular products to this same order and check out. The order is processed as a normal sale, but it is incorrectly flagged as a settlement, which can lead to error on codes depending on this. ## Desired behavior after PR is merged: After this fix, if a user leaves the payment screen during a **Settle Due** operation, the `is_settling_account` flag on the order will be correctly reset to False. task-id - 5144679 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#98463
This update fixes an issue where loyalty programs with pricelist restrictions weren't properly considered during POS transactions. Previously, if a POS session's pricelist didn't match a loyalty program's restrictions, the loyalty program would still be applied. Now, the system correctly checks pricelist compatibility, ensuring loyalty programs are only applied when the session's pricing aligns with the program's rules.
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 fixes an issue where the system was incorrectly using outdated number ranges when syncing data with DIAN. Previously, the system didn't properly check for the latest available ranges, leading to errors when clients requested new ranges. This ensures accurate DIAN data synchronization for our Colombian clients.
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 an issue where users could incorrectly save attendance records after attempting to change the associated employee. The fix ensures that only authorized users can update attendance records, improving data integrity and preventing potential errors. Test coverage has been added to confirm this change.
Original PR description
Closes [odoo/odoo#226007](https://github.com/odoo/odoo/issues/226007). Description of the issue/feature this PR addresses: Prevents a user from updating their attendance record by changing the employee to the one whose attendance is not managed by the current user. Current behavior before PR: - Assign the Officer Group of Attendance group to a user. - Assign the user as the attendance manager of itself. - Login with that user. - Create an attendance record for the employee and save it. - Try to change the employee and save; an error will be thrown as expected. - Go to the Attendance menu; the record will still be saved. Desired behavior after PR is merged: This commit ensures that un-allowed write does not take place + test coverage added. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243573 Forward-Port-Of: odoo/odoo#226335
27 changes
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
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
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
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.
12 changes
New functionality added to Odoo
This update adds support for payment channels in Thailand (TH), Malaysia (MY), and Vietnam (VN) through Xendit. This expansion allows Odoo users to accept payments from customers in these key Southeast Asian markets, improving our payment processing capabilities and customer reach.
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#189527
Enhancements to existing features
This update improves how combo products are displayed during order preparation. Previously, the POS system split combo items into separate orderlines due to price differences. Now, the preparation display will combine these orderlines for the same product, streamlining the process and making it easier to manage orders.
Original PR description
When ordering a combo product, the POS will split the included products from the extra products in different orderlines. This is done because of the extra products have a different price/unit than the extra items. But for the preparation display we don't care about different prices, so this PR will make the different orderlines of the same combo be merged in the preparation display if they target the same product. Task-[5473387](https://www.odoo.com/odoo/project/1737/tasks/5473387) Enterprise PR-[#104188](https://github.com/odoo/enterprise/pull/104188) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue where automated time tracking activities were delayed when exceeding allocated time limits. The fix ensures that dependent fields are correctly recomputed after pre-filter conditions are applied, preventing inconsistencies and delays in activity creation. This improves the reliability of time tracking workflows.
Original PR description
This PR is a cherry-pick of: https://github.com/odoo/odoo/pull/236323 When a pre-filter condition of an automation flushes fields, we must ensure that their recomputation is still scheduled…
This PR is a cherry-pick of: https://github.com/odoo/odoo/pull/236323
When a pre-filter condition of an automation flushes fields, we must ensure that their recomputation is still scheduled afterwards For example, if a rule pre-filters on field B (which depends on A), computing A should not clear the compute flag of B
### Issue:
In some automation rules, computed fields must be processed in a specific order (e.g., `effective_hours` -> `remaining_hours`)
However, if `remaining_hours` is referenced in the automation `Before Update Domain`, its compute flag may be incorrectly cleared, preventing the proper recomputation chain
This results in inconsistent behavior, such as delays in activities being created when timesheets exceed allocated time
### Cause:
The automation engine flushes fields referenced in the `Before Update Domain`, but does not restore their compute flags afterward Thus dependent fields are not recomputed as expected
### Steps to reproduce:
1. Enable Debug Mode
2. Create an Automation Rule
-- Name: Time Exceeded
-- Model: Task
-- Trigger: On Save
-- Before Update Domain: [("remaining_hours", ">=", 0)]
-- Apply on: [("remaining_hours", "<", 0)]
4. Create a Project with Timesheets
5. Create a Task inside the Project
6. Set Allocated Time to 10h
7. Use the Start button to record 11h (No activity appears in chatter)
8. Do the same again (Activity appears only after the second exceed) Before the fix, there is always a delay because the recomputation chain is broken
### Tickets:
18.0: opw-4409744
17.0: opw-5237430
Forward-Port-Of: odoo/odoo#243059
Forward-Port-Of: odoo/odoo#239667This update resolves an issue where saving company settings with duplicate VAT and Codice Fiscale (parent and branch) caused errors during proxy user setup. The fix ensures the correct company is identified during user searches, preventing conflicts and improving the stability of the Electronic Invoicing process. This ensures accurate EDI processing for multiple company setups.
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 addresses a bug where user edits within the website builder preview were lost. The system now immediately reverts the preview when text is entered or shortcuts are used, preventing conflicting state changes. This ensures a more reliable editing experience for users.
Original PR description
Forward-Port-Of: odoo/odoo#243039
This update fixes a critical issue where payroll sheets were incorrectly computed even when errors existed on payslips. Now, errors are properly flagged with a detailed message, ensuring payroll calculations are accurate and users are immediately alerted to resolve any problems. This prevents incorrect payments and improves payroll reliability.
Original PR description
Bug: When there is an issue on a payslip with an error level, and we try to compute the sheet, the sheet is computed. Instead of computing, it should raise and the message should specify what errors need to be resolved first. Cause: When computing the sheet, we were calling the self._get_error_message() without using the result, which is a string. Fix: Actually raise a ValidationError and use the result of self._get_error_message() for the error message. Introducing the raise brought other problems because some code supposed to fail was running seamlessly fine. But now, the raise is called and those needed to be solved as well. The issue raised multiple times is the "No contract in the payslip period". Task: 5153497
This update corrects a display issue in the Point of Sale (PoS) module where prices were incorrectly shown as excluding tax, even when tax-included settings were selected. The fix adjusts how prices are calculated to align with the PoS settings, ensuring accurate price displays for users. This improves the overall user experience and data consistency.
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
This update corrects a calculation error that occurred when offering part-time contracts. Previously, the system incorrectly attempted to adjust percentages based on full-time salaries. Now, the system accurately reflects the employer's contribution when a part-time offer is created, ensuring accurate payroll calculations.
Original PR description
When you make an offer to a 4/5 time for example, you set the 4/5 gross or employer cost and not the full, so no need to modify the percentage on the offer
This update resolves two issues related to overtime calculations in the payroll module. Specifically, it prevents the creation of overtime work entries when no paid rules are present in a ruleset, and it corrects a bug where regenerating work entries caused shifts in hours across consecutive days. This ensures accurate overtime calculations and payroll processing.
Original PR description
# Bug 1: ## Steps to reproduce: - Create an overtime ruleset and add rules. - Disable "Pay extra hours" on all rules in the ruleset. - Assign this ruleset to an employee. - Create an attendance that…
# Bug 1: ## Steps to reproduce: - Create an overtime ruleset and add rules. - Disable "Pay extra hours" on all rules in the ruleset. - Assign this ruleset to an employee. - Create an attendance that normally generates overtime. - Navigate to the work entries in payroll. - Overtime work entries are created! This fix will skip generating work entries when their will be no `paid` rules in a ruleset. # Bug 2: ## Steps to reproduce: - Create attendances with overtime for multiple consecutive days. - Navigate to Work Entries in Payroll. - Click on Reset->"Regenerate Work Entries” on the same period for bulk regeneration. - Observe that attendance and overtime hours are shifted between days. ### Fix: In `_get_overtime_intervals`, the overtime list was recreated inside the per-day loop, causing previously computed overtime intervals to be lost when multiple days were involved. Overtime intervals are now accumulated per resource across all days in the requested range before building the final Intervals. task - [5189151](https://www.odoo.com/odoo/project/1251/tasks/5189151)
This update ensures that the correct warehouse location is linked to merged manufacturing orders. Previously, the location information wasn't properly carried over, causing issues with multi-location workflows. This fix resolves a potential disruption in order fulfillment, particularly for complex manufacturing processes.
Original PR description
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in…
Situation ----- When applying a push rule after manufacturing a merged MO, there is an odd case where the link between the merged MO's transfer and the demand move breaks in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1054 because of the `m.location_id == move.location_final_id` part being false in https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/stock/models/stock_move.py#L1090-L1097 This is because, during the merge, `location_final_id` is not propagated to the new MO https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L2416-L2424 so when the new MO's `move_finished_id` gets computed https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L822 it gets the MO's `location_final_id` https://github.com/odoo/odoo/blob/5f8336c7d8ab891103a3035a9ebb5242cfa46ce6/addons/mrp/models/mrp_production.py#L1202 which is false. This leads to to the move getting the warehouse's default stock location thanks to https://github.com/odoo/odoo/blob/182a387d0ec6ad28d7d052d7100b2184372514be/addons/mrp/models/stock_move.py#L456-L457 This is problematic for complex use cases with multi-locations and custom routes. It should be safe to propagate the `location_final_id` of the merged MOs if they all share the same one. Use case example ----- <details> <summary>Full use case</summary> - Enable multi-step routes - Create location "WH/Stock/L1" - Create location "WH/Stock/L2" - Create Operation Type "MO child" - Type of Operation: Manufacturing - Sequence Prefix: MOCHILD - Source Location: L1 - Destination Location: L2 - Create Operation Type "Push Transfer" - Type of Operation: Internal Transfer - Sequence Prefix: L2L1 - Source Location: L2 - Destination Location: L1 - Create Route "MO child" - Create Rule "Manufacture" - Action: Manufacture - Operation Type: MO child - Source Location: False - Destination Location: Stock - Create Route "2-step" - Warehouse: Main WH - Create Rule "L1 -> Virtual/Production" - Action: Pull from - Operation Type: MO child - Source Location: L1 - Destination Location: Virtual/Production - Create Rule "Push: L2 -> L1" - Action: Push To - Operation Type: Push Transfer - Source Location: L2 - Destination Location: L1 - Unarchive MTO - Edit MTO route - Create Rule "L1 -> Virtual/production (MTO)" - Action: Pull - Operation Type: "My Company: Manufacturing" - Source Location: L1 - Destination Location: Virtual/Production - Supply Method: Trigger another rule - Create product "Main product" - Create product "Child product" - Routes: "MO child" & MTO - Create product "Material" (consumable) - Create BOM - Product: "Main product" - Component: "Child product" - Create BOM - Product: "Child product" - Component: "Material" - Create MO for "Main product" - Misc/Component Location set to L1 - Duplicate the MO - Merge child MOs & produce - Validate merged MO transfer to L1 - Go back to one of the "Main product" MO > Component quantity is 0 </details> ----- Ticket: opw-5144196 Forward-Port-Of: odoo/odoo#242373 Forward-Port-Of: odoo/odoo#240695
This update corrects a bug where delivery fees weren't accurately calculated when sales orders and company currencies differed. The fix ensures that delivery costs are correctly displayed based on the order's currency, preventing discrepancies in pricing. This improves the reliability of delivery cost reporting.
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 a crash that occurred when using integer rounding on accounting reports like Aged Receivable. The issue was caused by attempting to perform calculations with 'None' values, which resulted in an error. The fix skips rounding when a 'None' value is encountered, ensuring reports function correctly.
Original PR description
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to…
Currently, enabling the Integer Rounding option (e.g. 'Nearest') on accounting reports like Aged Receivable/Payable causes a crash when expanding lines if any column value evaluates to None. Steps to reproduce: 1) Install 'account_reports' module with demo data and enable developer mode. 2) Navigate to Accounting > Reporting> Partner Reports > Aged Receivable. 3) Click on 'gear icon' to navigate advance options. 4) Click on the Options tab and set Integer Rounding to 'Nearest', click save and close adv options. 5) Expand a partner line. Error: `TypeError: unsupported operand type(s) for /: 'NoneType' and 'int'` Root Cause: When integer rounding is enabled, the system iterates over formula results to round them using `float_round`(see[1]). However, specific report columns (such as totals for empty periods) may return None. The `float_round` function attempts to perform arithmetic on this value, failing because it cannot divide NoneType. FIX: Skip the rounding if the value received at [1] is None. [1]- https://github.com/odoo/enterprise/blob/9b517564d95424836da1e8368f6b5dc52ae45d1a/account_reports/models/account_report.py#L3329 opw-5392883 Forward-Port-Of: odoo/enterprise#102417
9 changes
New functionality added to Odoo
This update ensures Argentinian users can correctly issue credit notes by adding document type 110 - CREDIT NOTE TICKET, as required by AFIP regulations. Previously, this option was missing, causing errors when creating credit notes. This change improves compliance and usability for Odoo users in Argentina.
Original PR description
**Description of the issue/feature this PR addresses:** This PR adds the AFIP document type 110 - CREDIT NOTE TICKET, which is required for the Argentinian localization **Current behavior before…
**Description of the issue/feature this PR addresses:** This PR adds the AFIP document type 110 - CREDIT NOTE TICKET, which is required for the Argentinian localization **Current behavior before PR:** When users in Argentina tried to create a credit note for a ticket, the corresponding document type was not available as an option. **Desired behavior after PR is merged:** After this change, users can now select "110 - CREDIT NOTE TICKET" to issue the document correctly. [HERE](https://app.screencastify.com/watch/fVBWwSD6DAcodKO57qUZ) is a video replicating the issue 1) In localization Argentina, check document types and see that 110 CREDIT NOTE TICKET exists 2) Create a new journal as shown in the video 3) Create an invoice selecting that journal, and (83) TICKET as Document Type 4) Confirm the invoice and try to create a credit note. See that (110) CREDIT NOTE TICKET does not appear as an option --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue where users could incorrectly modify attendance records. The change now prevents unauthorized updates to attendance data, ensuring data integrity and accuracy. Test coverage has been added to guarantee this fix.
Original PR description
Closes [odoo/odoo#226007](https://github.com/odoo/odoo/issues/226007). Description of the issue/feature this PR addresses: Prevents a user from updating their attendance record by changing the employee to the one whose attendance is not managed by the current user. Current behavior before PR: - Assign the Officer Group of Attendance group to a user. - Assign the user as the attendance manager of itself. - Login with that user. - Create an attendance record for the employee and save it. - Try to change the employee and save; an error will be thrown as expected. - Go to the Attendance menu; the record will still be saved. Desired behavior after PR is merged: This commit ensures that un-allowed write does not take place + test coverage added. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#226335
This update resolves an issue where scheduled notifications and other mail-related processes would fail when records were deleted. The fix ensures that notifications are skipped when a record is deleted, preventing errors and improving the user experience by avoiding misleading notifications.
Original PR description
RATIONALE When a cascade delete occurs in DB, ORM methods are not called. More specifically loosely connected records using res_model / res_id pair are not removed when unlink override exists. SPECIFICATIONS Fix various use case in mail * notifications sent for scheduled messages; * failure notifications management; * activities mark as done; Task-5138556 Forward-Port-Of: odoo/odoo#238623 Forward-Port-Of: odoo/odoo#233071
This update resolves a bug in our expense reporting feature that caused incorrect journal entries and access errors. The fix ensures the report correctly uses the relevant expense line information (AML ID and company) for accurate navigation and data display.
Original PR description
Steps to reproduce: 1. Edit the first account.move in expenses account by adding Analytic Distribution to first aml. 2. Open General Ledger & group by Analytic Plan. 3. Click "View journal Entry" for the Bill line. Before this commit: When grouping financial reports by Analytic Plans, the temporary table generation logic incorrectly prioritized `account_analytic_line` over `account_move_line` ids and companies. This caused the report to use Analytic IDs as row identifiers, leading to "Identity Theft" where clicking a row opened an unrelated Journal Item (sharing the same integer ID) or raised Access Errors due to company mismatches. After this commit: The report table now uses the aml id as intended and redirects to the expected journal entry. opw-5413138 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#103930
This update fixes incorrect tax codes used in Odoo's account_edi_ubl module, specifically related to Bebat (battery recycling) and EPD charges. It ensures accurate reporting of recycling taxes by using the correct codes (CAV for Bebat and 64 for EPD), aligning with regulatory requirements. This improves the accuracy of financial reporting for these specific transactions.
Original PR description
[FIX] account_edi_ubl_cii: EPD allowance/charge code should be 64, not 66 64 stands for "Special agreement" 66 stands for "New outlet discount" opw-5478324 [FIX] account_edi_ubl_cii: Bebat allowanceChargeReasonCode should be CAV Bebat is a non-profit organization in Belgium that collects, sorts, and recycles used batteries. Currently, whatever the recycling tax applied, we report is as AEO for "Collection and recycling - The service of collection and recycling products." However, since Bebat is about recycling batteries, we have to use CAV instead for "Battery collection and recycling - The service of collecting and recycling batteries." opw-5474752 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an error in how price differences are calculated for subcontracted products. Previously, the system incorrectly compared costs in different currencies, leading to inaccurate price difference invoices. Now, the system converts component costs to the invoice currency, ensuring accurate price difference calculations and preventing erroneous invoice lines.
Original PR description
Problem: When computing the price difference on a vendor bill for a subcontracted product, the component cost is considered in the company's currency regardless of the currency of the invoice. This…
Problem: When computing the price difference on a vendor bill for a subcontracted product, the component cost is considered in the company's currency regardless of the currency of the invoice. This means the price difference calculation directly compares two different currencies without converting them, resulting in some incorrect values for the price difference invoice lines. Solution: We will convert the component cost to the invoice currency when computing price difference. Steps to reproduce (runbot 18): - Product with - Standard price auto - BoM: sbc, one component with nonzero value (e.g. $1) - Nonzero value (e.g. $5) - Another currency 1. Create a PO for the subcontracted product 2. Set the Invoice currency to something other than the company default 3. Confirm the PO and validate the sbc and receipt 4. Create the vendor bill, and bill for the correct value (Whatever $4 is in the invoice currency) A price difference line will be erroneously generated for some nonsense value, when we expect 0 price difference. opw-5232917
This update fixes a discrepancy in eWaybill invoices for India by including reverse charge (RC) amounts in the total invoice value. Previously, the eWaybill data didn't align with Odoo and the Indian government's system. This change ensures accurate reporting and compliance with GST regulations.
Original PR description
For export invoices, the total invoice value in the eWaybill JSON did not include reverse charge amounts for GST, leading to a mismatch with the value shown in Odoo and the eWaybill generated by the Indian government system. This commit adjusts the JSON computation to include the reverse charge amounts in the total invoice value for exports, aligning it with the government-generated eWaybill, while preserving the existing reverse charge flow. task-5068199
This update resolves a validation error that occurred when creating partial backorders within wave transfers. The issue stemmed from the system incorrectly processing ongoing batches, leading to a user error. This fix ensures that wave transfers are correctly validated, preventing disruptions in the stock management process.
Original PR description
## How to reproduce: - Enable Wave transfert in setting - Go to the Receipt Operation type: - Create Backorder: always - Automatic Batches: Enabled - Wave Grouping: Products - Create and confirm…
## How to reproduce:
- Enable Wave transfert in setting
- Go to the Receipt Operation type:
- Create Backorder: always
- Automatic Batches: Enabled
- Wave Grouping: Products
- Create and confirm (don't validate) 2 Receipts for 10 units of a storable product P
- The 2 receipt should have been added to a new wave transfer with 2 lines for P
- On the first line, set the quantity to 0
- On the second line, set the quantity to 1
- Try to validate the wave transfer ==>> UserError "The following transfers cannot be added to batch transfer WAVE/XXXX. Please check their states and operation types."
## Issue:
Backorders are generated before the current batch is marked 'done' (it waits for empty pickings to be detached). The auto-batch logic incorrectly identifies the current 'in_progress' batch as a candidate for the new backorders, attempting a merge that violates validation constraints.
## Solution:
Exclude the current wave/batch from the auto_wave search domain using a context variable passed during validation.
OPW-5413921
---
Test result before fix:
```
2026-01-13 10:37:26,541 27952 INFO oes_test_18.0 odoo.addons.stock_picking_batch.tests.test_auto_waving: Starting TestAutoWaving.test_auto_wave_skip_current_batch ...
2026-01-13 10:37:26,820 27952 INFO oes_test_18.0 odoo.addons.stock_picking_batch.tests.test_auto_waving: ======================================================================
2026-01-13 10:37:26,820 27952 ERROR oes_test_18.0 odoo.addons.stock_picking_batch.tests.test_auto_waving: ERROR: TestAutoWaving.test_auto_wave_skip_current_batch
Traceback (most recent call last):
File "/home/odoo/Odoo/src/18.0/odoo/addons/stock_picking_batch/tests/test_auto_waving.py", line 440, in test_auto_wave_skip_current_batch
wave.action_done()
File "/home/odoo/Odoo/src/18.0/odoo/addons/stock_picking_batch/models/stock_picking_batch.py", line 264, in action_done
return pickings.with_context(**context).button_validate()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/Odoo/src/18.0/odoo/addons/stock_picking_batch/models/stock_picking.py", line 145, in button_validate
res = super().button_validate()
^^^^^^^^^^^^^^^^^^^^^^^^^
...
File "/home/odoo/Odoo/src/18.0/odoo/odoo/fields.py", line 1418, in __set__
records.write({self.name: write_value})
File "/home/odoo/Odoo/src/18.0/odoo/addons/stock_picking_batch/models/stock_picking.py", line 112, in write
self.batch_id._sanity_check()
File "/home/odoo/Odoo/src/18.0/odoo/addons/stock_picking_batch/models/stock_picking_batch.py", line 323, in _sanity_check
raise UserError(_(
odoo.exceptions.UserError: The following transfers cannot be added to batch transfer WAVE/00012. Please check their states and operation types.
```
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prA bug was preventing employees from taking future leave when their accrued balance was below the maximum limit. This update corrects the calculation of available leave days, ensuring employees can continue to accrue and take leave as intended. The fix ensures accurate leave allocation based on accrual plan rules.
Original PR description
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be. #…
Accrual plan for leave days gets blocked, even when the remaining leave balance is below the cap. As a result, no additional leaves are accrued beyond a certain point, even though they should be.
# Steps to reproduce:
Go to time off app
* Create a new leave type.
* Create a new accrual plan with:
- one milestone :
- 2 days accrued per month
- Cap: 10 days
- start accruing 1 days after
- No expiration
- Carry over: All
* Create and validate a leave allocation
- 1 year ago
- new leave type
- new accrual plan
* Take the maximum number of leaves available.
* Advance the computer calendar by 1 year.
* Again, take the maximum number of leaves.
* Advance the computer calendar by another year.
* Try to take a future leave.
-> Issue: It’s not possible to take a future leave, the number of accrued days has stopped increasing. The accrual plan appears blocked.
Objective : The accrual plan should continue to allocate leave days even if leaves have been consumed regularly, as long as the remaining leaves are under the cap.
## Issue
Before going further: the property `leaves_taken` of the `hr.leave.allocation` is supposed to contain the number of leaves this allocation cover until "today".
In the `_test_get_allocation_future_leaves1` added test, in the last line of the test :
`assert_virtual_leaves_equal(self, leave_type_day, 2, self.employee_emp, date='2023-02-01')`
When calling `get_allocation_data` with a `target_date` set in the future, the result is wrong. Here is how it works :
`get_allocation_data`
...
.....`_get_consumed_leaves` (1)
...........`_get_future_leaves_on` (2)
...............`_process_accrual_plans` (3)
....................`_compute_leaves` (4)
.........................`_get_consumed_leaves` (5)
..............................`get_future_leaves_on` (6)
...................................`process_accrual_plans` (7)
**A)** The method **(2)** try to calculate the added number of days each allocation will have on `target_date`. So it creates a copy of the allocation in memory using the 'new' method:
`fake_allocation = self.env['hr.leave.allocation'].with_context(default_date_from=accrual_date).new(origin=self)`
It will then update it to `target_date` using `_process_accrual_plans` and will return the difference of days between the
updated `fake_allocation` and the current allocation (`self`)
**B)** Before iterating over each accrual date, the `_process_accrual_plans` **(3)** will get the `leaves_taken` property which is a computed field. It will trigger `_compute_leaves`.
**C)** The method **(4)** will call `_get_consumed_leaves`, and so the nightmare begins.
**D)** The method **(6)** will create a second `fake_allocation` based on the origin of the first `fake_allocation` (see **A)**).
**E)** This time, `_process_accrual_plans` **(7)** will also look at the `leaves_taken`, but won't trigger the `_compute_leaves` probably because the current allocation is a `fake_allocation` of a `fake_allocation`, and one property of the `new` method is that `Two new records with the same origin record are considered equal.`. Therefore, the `leaves_taken` is considered to be already computed (but it's not).
So `_process_accrual_plans` read the `leaves_taken` which is 0 (probably the default value of `leaves_taken`), but it should be 20 !
**F)** As the value of `leaves_taken` is wrong, the fake_allocation n°2 is also wrong, and its `number_of_day` is 10 but the `number_of_days` of the origin allocation is 20. So `get_future_leaves_on` **(6)** will return -10 which makes no sense, and all the previous calls computations will be wrong. And the final `virtual_remaining_leaves` value will be 0 instead of 2.
## Source of the issue
In the `_process_accrual_plans` method, for each allocation, `leaves_taken` is only computed once at the start of the loop over the allocation "important" dates (see `nextcall` property of `hr.leave.allocation`). At this moment, the method calculates the `leaves_taken` the allocation will have on the `accrual_date` parameter. Yet, this property can change depending on the date the allocation is on (`nextcall` property) which leads to some issues in the computation of the `allocation.number_of_days`.
## Solution
For each allocation, compute the `leaves_taken` at every iteration trough the values of `nextcall`. BUT, this can trigger an infinite loop as computing `leaves_taken` calls `_get_consumed_leaves` which calls `_get_future_leaves_on`, which calls `_process_accrual_plans` ... To avoid this, this PR add the context variable `precomputed_allocations` (will be converted into a function parameter in master) which will prevent `_get_consumed_leaves` from calling `_get_future_leaves_on` for the allocations already up to date (contained by this very `precomputed_allocations` context variable).
**For r+: Needs a few changes at 18.0 (hours per day of employee is retrieved differently for example)**
opw-4934391
opw-5226806
Forward-Port-Of: odoo/odoo#2398361 change
Resolved issues and error corrections
This update corrects a potential issue with the transmission of payroll data to the Swiss tax authorities (ELM). By using a reference date when locking payroll periods, the system now accurately reflects the correct tax reporting timeframe, ensuring compliance and reducing the risk of errors.