Wednesday, January 14, 2026
23 changes · saas-19.1
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
Code cleanup and technical improvements
This update centralizes rental pricing within Odoo, replacing previous app-specific models with a flexible pricelist system. This simplifies product configuration, enables dynamic pricing based on rental periods (hours, days, etc.), and improves consistency across the Sales and Rental applications. The changes also update the eCommerce frontend to reflect these new pricing capabilities.
Original PR description
This update simplifies product pricing management by consolidating all pricing configurations – Sales, Rentals, and Subscriptions – into a single, easy-to-use interface. This improves efficiency for users and ensures consistent pricing across the Odoo ecosystem, particularly for eCommerce and rental products.
Original PR description
The primary goal of this PR is to unify product pricing management across the Odoo ecosystem by centralizing configurations for Sales, Rental, and Subscription applications within the core pricelist…
The primary goal of this PR is to unify product pricing management across the Odoo ecosystem by centralizing configurations for Sales, Rental, and Subscription applications within the core pricelist engine. This consolidation introduces a single "Prices" tab on the product template form, effectively replacing fragmented, app-specific views with a unified interface. To improve daily efficiency, the PR enables users to quickly manage fixed-price rules through an inline editable interface directly on the product form, while still providing access to the full pricelist engine for more complex configurations. On a technical level, the pricelist engine has been evolved to support the temporal and contextual needs of dependent applications; this includes dissociating the date used for rule application from the date used for currency conversion, as well as propagating request contexts during eCommerce price computations. task-5375343 See also: - https://github.com/odoo/enterprise/pull/102625 - https://github.com/odoo/upgrade/pull/9172 --- To accelerate this PR, it was decided to rebase the work on an ongoing PR [^1][^2] refactoring and greatly facilitating the interactions backend-frontend of the eCommerce/Rental applications. Thx Louis 😉 (and Victor for thinking about it) [^1]: https://github.com/odoo/odoo/pull/234405 [^2]: https://github.com/odoo/enterprise/pull/98161
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
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 now correctly priced based on the sales order's currency, preventing discrepancies in pricing. This improves the reliability of delivery cost calculations.
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 ensures that loyalty programs with pricelist restrictions are properly considered when a customer makes a purchase in the POS. Previously, the system would incorrectly apply loyalty programs even if the customer's purchase didn't match the program's pricing rules. This fix corrects a bug related to pricelist availability and ensures accurate loyalty program application.
Original PR description
Before this commit, if a loyalty program had pricelist restrictions, the POS would not consider them when loading the applicable loyalty programs. This could lead to scenarios where a loyalty program was applied in a POS session even if the session's pricelist was not allowed by the program. This happened when the pricelist was also not available in the POS configuration and program.pricelist_ids was empty. opw-5467990 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#242279
This update resolves a 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 invoice errors and improving data accuracy. This impacts invoice processing with Colombian DIAN regulations.
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 fixes an issue where part-time employee time off calculations incorrectly included company working days, even when those days were holidays. Now, time off is accurately calculated based on the employee's actual work schedule, ensuring correct holiday pay is applied. This improves payroll accuracy and compliance.
Original PR description
Currently when a employee has a diferent working schedule than the company's one (part time employee), when he takes time off the computation includes days where he is not working but is an active working day for the company. That is not considering holidays. e.g. -employee works monday to wednesday -company works monday to friday -there is a holiday on the thursday taking monday to wednesday should count 4 days. added holidays support for this case opw-5082080 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#240299 Forward-Port-Of: odoo/odoo#228960
This update fixes a bug preventing AI server tools from running correctly. The issue stemmed from an unnecessary inclusion of '__end_message' in tool arguments, causing validation errors. The fix removes this element before tool execution, ensuring reliable AI tool operation.
Original PR description
When executing AI server actions, tools with `ai_tool_schema` defined would fail with "Missing definition for __end_message" error. Root cause: - `_prepare_tools` adds `__end_message` to the schema sent to the LLM - The LLM returns tool calls with `__end_message` in arguments - `_ai_tool_run` validates arguments against the original schema (which doesn't have `__end_message`) - Validation fails with "Missing definition for __end_message" Fix: Use `pop` instead of `get` to extract and remove `__end_message` from arguments before calling the tool executor. This ensures that it's not passed to the tool validation. TASK-ID: 5423756
This update fixes an issue where the 'Out of Contract' duration was incorrectly calculated, leading to inaccurate reporting. The change ensures that contract overlap dates are capped by the payslip period's start and end dates, providing more reliable payroll data. This improves the accuracy of employee compensation calculations.
Original PR description
Steps to Reproduce: 1. Create a contract ending early in the year (e.g., February). 2. Compute a payslip for a much later period (e.g., November). 3. The "Out of Contract" line shows an excessive number of days (counting from Feb to Nov). Reason: - If a contract ends before the payslip period, it adds all days from the end of the contract until the end of the payslip period as "Out of Contract", ignoring the payslip start date. - If a contract starts after the payslip period, it adds all days from the payslip start date until the contract start date, ignoring the payslip end date. Solution: Constrain the calculated "Out of Contract" dates using `max()` and `min()` to ensure they never exceed the payslip's `date_from` and `date_to`. Task: 5350519 Forward-Port-Of: odoo/enterprise#100694
This update resolves a bug where the 'Working Time to Assign' field incorrectly remained at 0 when assigning tasks after switching between companies with time off. The fix ensures that the system accurately calculates working time based on the last stage change and considers company-specific holiday impacts, preventing incorrect time assignments.
Original PR description
__ ## Short functional explanation of the error Let's say we have 2 companies: company A and company B. We create a public time off of a few days starting before today and ending 2 days later in…
__ ## Short functional explanation of the error Let's say we have 2 companies: company A and company B. We create a public time off of a few days starting before today and ending 2 days later in company A, then switch back to company B. In company B, we create a project and a task, and assign this task. The working time to assign will stay at 0. ## Reproduction Steps 1. Switch to company A and create a timeoff starting before today and ending later. 2. Switch back to company B. Create a project, a stage and a task. 3. Enable the debugger. 4. The field Working Time to Assign is invisible by default, so open studio, click on View, and check Show Invisible Elements. 5. Click on the tab Extra info and on the block Working time to assign. Uncheck Invisible. 6. Close studio and assign someone to the task. Make sure that you do this operation at a different time than the one recorded for the last stage change. ### Expected behavior The hours under Working Time to Assign should compute the difference between the last time the task got its stage changed and the time of assignation ### Unexpected behavior Nothing happens ## Origin of the issue When computing the working time to assign, we also take into consideration leaves: if this happened during public holidays, we consider that it took no working time to get assigned. However, when a holiday is set in another company, the Working Time to Assign duration will be impacted, as the domain to retrieve the corresponding leaves is the following: https://github.com/odoo/odoo/blob/c7e965a61b7ce856c2daa8e2574cf4c60caf7a20/addons/resource/models/resource_calendar.py#L537-#546 The company isn't taken into account in the domain, applying the holiday for every company. _________________________________________ opw-5222883 Forward-Port-Of: odoo/odoo#242228 Forward-Port-Of: odoo/odoo#236043
This update significantly speeds up the website builder by optimizing how snippets are retrieved. The fix eliminates a slow process of searching through snippets, resulting in faster page loading times and a smoother user experience. It addresses a performance bottleneck impacting website builder responsiveness.
Original PR description
__Before commit:__ The method `getOriginalSnippet` is called hundreds of times per website builder test inside the `disableUndroppableSnippets` method from `DisableSnippetsPlugin`. Each time, it recreates the same snippet array and loops through them to find one snippet by its name. This may take around 100 ms for a single website builder test. Moreover, `getOriginalSnippet` loops through `snippetStructures`, which includes the custom snippets. This is unnecessary, since snippet names are equal to the value of `data-snippet`, which is always copied from the base snippet when a custom one is created. __Fix:__ Create an object for which the snippet `name` values are the keys and each value is the first snippet having this `name`. This allows `getOriginalSnippet` to retrieve a snippet in `O(1)` instead of `O(n)` and reduces total time spent in this function to virtually nothing. task-5269391 Forward-Port-Of: odoo/odoo#243372 Forward-Port-Of: odoo/odoo#243102
This update corrects a potential issue with the transmission of ELM (Einnahmen-Lohn-Meldung) data for Swiss payroll. By using a reference date when locking payroll periods, the system now accurately reflects the correct reporting timeframe, ensuring compliance and reliable data transmission. This resolves a technical problem that could have resulted in inaccurate reporting.
Original PR description
Forward-Port-Of: odoo/enterprise#104269
This update resolves a problem preventing the migration of Odoo 16 to 19.1 for the Italian localization (l10n_it) module. The migration process failed because a required column was missing. This change adds the necessary column, ensuring a smooth and successful upgrade for Italian businesses using Odoo.
Original PR description
Migration from 16.0 fails because l10n_it_exempt_reason column does not exist Forward-Port-Of: odoo/odoo#240862
The primary goal of this PR is to finalize the unification of product pricing across Odoo Enterprise by migrating the Rental and Subscription applications to the core pricelist engine. This change…
The primary goal of this PR is to finalize the unification of product pricing across Odoo Enterprise by migrating the Rental and Subscription applications to the core pricelist engine. This change eliminates legacy, app-specific pricing models in favor of a centralized and more capable architecture. This consolidation integrates Subscription and Rental pricing directly into the unified *Prices* tab introduced in the base module. For Subscriptions, recurring prices are now managed alongside standard rules. For Rental, the rigid `product.pricing` model and legacy configuration settings (such as static delay fines) are removed. Instead, users define rental prices using standard pricelist items, supported by a new `periodicity` configuration (Hours, Days, Weeks, Nights) on the product form. On a technical level, the rental engine has been refactored to leverage the full capabilities of the pricelist system, enabling previously unavailable features like formula-based pricing and variant specific extra-price. The eCommerce frontend has been updated to support this dynamic logic, ensuring that availability constraints, periodicity display, and price computations are consistent with the new backend architecture. task-5375343 Co-authored-by: Lionel Piraux <lipi@odoo.com> Co-authored-by: Victor Feyens <vfe@odoo.com> Co-authored-by: Louis Tinel <loti@odoo.com>