Monday, January 12, 2026
15 changes · 18.0
New functionality added to Odoo
This update adds support for payment channels in Thailand, Malaysia, and Vietnam through Xendit. This expansion allows Odoo users to accept payments from customers in these key Southeast Asian markets, improving our payment options and expanding our business 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
Resolved issues and error corrections
This update fixes an issue where discounts applied to repair quotations weren't correctly carried over to the linked sales order lines. The fix removes a faulty process that was resetting the discount calculation, ensuring accurate pricing on sales orders generated from repair quotes. This improves the reliability of the repair order process and prevents pricing discrepancies.
Original PR description
**Steps to reproduce:** * Install the **Repair** module with demo data. * From Setting -> enable 'Discounts' and 'Pricelists' * From the home screen, search for Pricelist and open it. * Open the…
**Steps to reproduce:** * Install the **Repair** module with demo data. * From Setting -> enable 'Discounts' and 'Pricelists' * From the home screen, search for Pricelist and open it. * Open the default USD pricelist and go to Configuration → `Show public price & discount to the customer` * Open the *Repair* app. * Create a **Repair Order with parts**. * Click **Create Quotation** button from the repair order. * In the quotation, order line and set a **discount**. * Return to the repair order using the **Repairs** smart button. * Confirm the repair order, then **Start repair** and **End repair** order. **Observed behavior:** * The discount added on the quotation line disappears from the linked sale order line. **Cause:** * The `discount` field on `sale.order.line` is computed by `_compute_discount`, which `depends` on `product_id`, `product_uom`, and `product_uom_qty`. When `product_uom_qty` is written during `action_repair_done`, the compute method is triggered and the `discount` is recalculated. https://github.com/odoo/odoo/blob/49169c4c4fec57d78cd82c4c9366de9d69540e6a/addons/repair/models/repair.py#L457 **Fix:** * Remove the for loop that calls `write()` on the sale order lines, as it is functionally incorrect and causes the discount to be reset. --- opw-5352567 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#238410
This update fixes an issue where invoices generated with complex certificates (multiple similar RDNs) failed validation by official Spanish tax authorities. The fix ensures all certificate details are correctly processed, resolving validation errors and ensuring compliance with regulatory requirements. This improves the accuracy of our Facturae EDI documents.
Original PR description
When a certificate contains multiple RDNs of the same type (for example several OU entries), the generated issuer is incorrect. This happens because the current implementation relies on a dictionary to sort the RDNs, causing duplicate keys to be overwritten. Steps to reproduce: - Create a certificate with multiple OU RDNs - Upload the certificate in Odoo - Generate the Facturae EDI document - Validate it using official tools: https://face.gob.es/es/facturas/validar-visualizar-facturas https://valide.redsara.es/valide/ejecutarValidarFirma/ejecutar.html The validation fails because the issuer is incorrect. This commit fixes the issue by sorting RDNs using a priority-based list, ensuring all RDNs are preserved and ordered correctly. opw-5408225 opw-5380996 opw-5253287 Forward-Port-Of: odoo/odoo#241094
This update fixes an issue where GS1 barcodes weren't accurately reflecting the quantity of products being produced in manufacturing orders. Previously, the system only added one unit regardless of the barcode's quantity. Now, the system correctly uses the quantity specified in the GS1 barcode when updating the finished product's quantity, ensuring accurate tracking of production output.
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#95174
This update resolves an issue where country-based filtering within work entries was not functioning correctly, leading to errors. The fix ensures accurate country-based searches and filtering, eliminating module loading problems. This improves the reliability of work entry data.
Original PR description
Issue: The country_id related field on work entries was not stored, causing domain filters and search on this field to fail and triggering client-side errors. Fix: Use search parameter on field to write function so field can be used safely in search domains and filters. Impact: Country-based filtering now works correctly without triggering module loader errors. Task: 5406904
This update resolves an issue where country-based filtering on payslips and payslip runs wasn't functioning properly, leading to errors. The fix ensures accurate country-based filtering, preventing module loading problems and improving the reliability of payroll reports.
Original PR description
Issue: The country_id related field on payslip and payslip run was not stored, causing domain filters and search on this field to fail and triggering client-side errors. Fix: Use search parameter to write function so field can be used safely in search domains and filters. Impact: Country-based filtering now works correctly without triggering module loader errors. Task: 5406904
This update resolves a bug in the General Ledger reporting that caused incorrect journal entry displays when using analytic accounting. Specifically, the system was misinterpreting line IDs, leading to duplicate entries and incorrect links. The fix ensures accurate grouping and navigation within the General Ledger.
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
This update resolves an issue where failed electronic payments in Point of Sale would leave transactions in a blocked state, preventing cancellation. A new 'Force Cancel' button has been added to allow users to manually unblock and cancel these payments, improving the user experience and preventing data inconsistencies.
Original PR description
Before this commit, if an electronic payment failed (e.g. due to the payment terminal/IoT box not being reachable) and the user subsequently tried to cancel the payment from the POS, they would reach a blocked state. The payment never cancels but it cannot be deleted. This commit adds a 'Force cancel' button, similar to the 'Force done' button already present, to allow the user to get unblocked in this situation. task-5485237 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where Odoo incorrectly used outdated number ranges when syncing data with the DIAN tax authority. Previously, the system didn't reliably update number ranges, leading to errors when clients requested new ranges. This change ensures that the latest, valid number ranges are used for DIAN data synchronization, preventing invoice processing problems.
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.).
This update resolves a bug that occurred when switching between accounting contexts (COAs) in the Point of Sale (PoS) module. Specifically, it prevents a database error related to payment method configurations, ensuring a smoother transition between fiscal localizations. This change improves stability and prevents disruptions to PoS operations.
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
This update restricts public users' ability to modify department configurations within the Employees app. Previously, they could edit all settings, which was a security vulnerability. This change ensures public users can only view department information, improving data integrity and security.
Original PR description
**Steps to reproduce:** - Install Employees app - Login as public user - Go to Employees menu - Press on any employee to open its form view - Press on the department field - Try to edit the department configuration **Issue:** Public users can edit all the fields on the department configuration, except the Department's manager. This is should not be the case. **Solution:** Remove write access on department for public users. Task: 5384463
This update corrects an issue where currency rates were incorrectly applied to cost of goods calculations, leading to inaccurate financial reporting. The fix ensures that cost calculations are based on the intended currency, regardless of currency rate changes, improving accounting accuracy.
Original PR description
**Steps to reproduce:** - in settings enable "automatic accounting" and "anglo-saxon accounting" - make sure dollar is the main currency - activate euro as another currency - set a rate for today as…
**Steps to reproduce:**
- in settings enable "automatic accounting" and
"anglo-saxon accounting"
- make sure dollar is the main currency
- activate euro as another currency
- set a rate for today as 1$->10 euros
- set another rate for a week ago 1$->2euros
- create a storable product with standard price/automated
category and a cost of 10
- create a new invoice for 1 unit of your product
- do not set a date on the invoice
- set the currency as euro
- click on the calendar widget to choose the rate and select the
date of yesterday
(- the rate applied should now be 1$->2euros)
- confirm the invoice
**Current behavior:**
the cogs line (credit stock interim delivered and debit expenses)
have a value of 5
**Expected behavior:**
the cogs value should be 10. It shouldn't be impacted by the
currency rate.
**Cause of the issue:**
when the invoice is confirmed, because there is no date,
the date is set at today inside _post()
https://github.com/odoo/odoo/blob/626d06734991bcd3b94a6c9454317f311164e9dc/addons/account/models/account_move.py#L5090
This results in a call to write with invoice_date in the vals.
Inside the override of the write() method of AccountMove,
the call to super is inside a 'with self._sync_dynamic_lines' bloc.
https://github.com/odoo/odoo/blob/626d06734991bcd3b94a6c9454317f311164e9dc/addons/account/models/account_move.py#L3413-L3419
So the first part (up until the yield) of _sync_dynamic_lines is
executed before the call to super.
In _sync_dynamic_lines() the yield is inside a 'with _sync_invoice'
bloc.
https://github.com/odoo/odoo/blob/626d06734991bcd3b94a6c9454317f311164e9dc/addons/account/models/account_move.py#L3239-L3241
As a result, the first part of sync_invoice() (until the yield) is
executed before the call to super method write().
https://github.com/odoo/odoo/blob/626d06734991bcd3b94a6c9454317f311164e9dc/addons/account/models/account_move_line.py#L1513-L1515
And the second part is executed after the call to write() and
after the update of line_container['records'] inside
_sync_dynamic_lines().
Because the change of date, changes the currency_rate,
changed('currency_rate') will return True, and the balance will
be recomputed for each line.
https://github.com/odoo/odoo/blob/0dabb221225fba96c0e55779afadd9f12b369777/addons/account/models/account_move_line.py#L1524-L1530
This causes 2 problems:
1) for the non cogs line, the rate set manually by the user
is replaced by the rate of today
2) for the cogs line, a rate is applied where no currency
rate should be applied at all.
The problem 1) was fixed in this PR https://github.com/odoo/odoo/pull/239012
But this does not fix problem 2) as the fix consists in letting the
recomputation happen for the balance of the account move lines
and then re-recompute their balance in the manually set currency_rate.
Whereas for our cogs line we need no currency_rate based
recomputation at all.
**fix**
prevent balance recomputation based on currency_rate change
for cogs lines.
opw-5266804This update corrects a technical error in the French language version of Odoo that was impacting how tax reports were generated. Specifically, a miscalculation in the 'box 15_1' was identified and resolved. This ensures accurate tax reporting for French businesses using the Odoo platform.
Original PR description
During this commit: https://github.com/odoo/odoo/commit/869f80b466ec2246f27e11fa823eb32ac664fb01 we made a mistake in the box 15_1. no task id --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#243013
This update resolves an issue where reordering rules would incorrectly attempt to update locked manufacturing orders (MOs) after a quality check. The fix ensures that the system correctly handles locked MOs, preventing errors and maintaining data integrity during reordering processes. This improves the reliability of the MRP workflow.
Original PR description
### Issue: In 18.0-18.2, for product with a Manufacturing BoM containing a Component, a WO and a Quality Point If a Reordering Rule is triggered, odoo try to add the newly ordered quantity to an…
### Issue: In 18.0-18.2, for product with a Manufacturing BoM containing a Component, a WO and a Quality Point If a Reordering Rule is triggered, odoo try to add the newly ordered quantity to an existing MO But if the MO is "locked" because a quality check has been performed, a Error is raised: ``` Odoo Warning You cannot update the quantity to do of an ongoing manufacturing order for which quality checks have been performed. ``` ### Steps to reproduce: - Create a product tracked by quantity - Add a BoM (1 component tracked by Quantity, 1 Operation with 1 Quality Point) - Create a Reordering Rule (Route: Manufacture, Trigger: Manual, Min/Max: 1) - Click on Order - Open the created MO and the Shop Floor (Remove the filters to see the WO) - Complete the Quality Point - Modify the Reordering Rule (Min/Max: 2) - Click on Order - the error should be raised ### Cause: The MO to update is retrieved here: https://github.com/odoo/odoo/blob/45184da06cf7b92a48e3e4e90bf8b285bdd9ad6a/addons/mrp/models/stock_rule.py#L53-L57 Using a domain defined in this function: https://github.com/odoo/odoo/blob/45184da06cf7b92a48e3e4e90bf8b285bdd9ad6a/addons/mrp/models/stock_rule.py#L130-L153 In 18.0-18.2, when validating a `quality check` from the Shop Floor while the WO is in `waiting` state, the MO remains in `confirmed` state This makes the domain match the current WO and MO, triggering `change_prod_qty` even though the MO is locked In 18.3–18.4, a similar issue can occur with multiple WOs when the first blocks the second and a `quality check` is performed on the latter The `blocked` state behaves like `waiting`, but the issue is avoided when using the Shop Floor because this commit ensures that clicking a card starts the timer and changes the state to `progress`: https://github.com/odoo/enterprise/pull/84425/commits/67c2127424ef3a1eb4794edd2c262b94ef186561 However, it could still theoretically be triggered under specific conditions In 19.0, the new stock.reference system (https://github.com/odoo/odoo/pull/212679) ensures the MO is detected as different, so a new one is always created opw-5012588
This update significantly speeds up the process of determining user permissions for documents. Previously, the system was slow due to redundant queries and inefficient processing of large document sets. The change optimizes the system to fetch only relevant access records, resulting in a 15x performance improvement.
Original PR description
Before this commit, computing a user's permission on a specific document relied on the `_get_permission_without_token` method, which was responsible for determining user's permission on a **single…
Before this commit, computing a user's permission on a specific document relied on the `_get_permission_without_token` method, which was responsible for determining user's permission on a **single document**. However, this approach had two key performance bottlenecks: 1. The method filtered accesses using the `access_ids` field from the `document.document` model, which could include accesses belonging to **other users**, resulting in redundant records being queried. 2. Since it only handled **one document at a time**, it triggered multiple ORM calls when dealing with large recordsets, leading to performance overhead. After this commit, the computation process has been optimized by utilizing the uniqueness constraint on the `(partner_id, document_id)` tuple in the `document.access` model. Instead of querying per document, we now: - Fetch **all access records** related to the **current logged-in user** in a single query. - Apply an additional filter to restrict results only to documents within the recordset. This eliminates redundant queries. The benchmark below is done on a usecase where 4 calls to the `_compute_user_permission` has been invoked, with a recordset of 1000 documents each. The usecase queried **198316** accesses containing accesses of other users. In the improved version it only queried the accesses upper bounded by the number of documents in the recordset. --- | Scenario | Time (seconds) | |-----------|----------------| | **Before** | **20s** | | **After** | **4s** | ---