Daily updates from Odoo
Thursday, May 21, 2026
22 changes · 18.0
Enhancements to existing features
This update adjusts how global discounts are exported in Odoo to align with UBL (Universal Business Language) standards. Previously, discounts were represented as negative invoice lines, which is now corrected by representing them as ‘Allowances’. This change ensures proper compliance with international trade regulations and simplifies UBL invoice generation.
Original PR description
Export global discounts as Allowances instead of negative invoice lines to comply with UBL specifications. task-5900496 --- 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 a visual issue where the Timesheet Kanban header and dropdown menus were overlapping. The problem stemmed from a styling element (position-sticky) that created a stacking context conflict. Removing this element allows the header to be properly positioned, improving the user experience.
Original PR description
Steps to reproduce: - Open Timesheets. - Switch to kanban view. - Groupby any field. - Start timer and click on task/project field. Issue: - Kanban Header and Dropdown menu of selection overlap. Reason: - It is due to the usage of `postion-sticky` on the header thus creating it's own stacking context, so header and Kanban Renderer body work in different stacking context, thus overlapping each other where they shouldn't have. For more info refer: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/position#sticky Fix: - Remove `postion-sticky` as it doesnt serve any purpose as header can now work being a static postioned node. task-4714235 Forward-Port-Of: odoo/enterprise#103142
A test was failing due to a mismatch in how dates were interpreted across different timezones. This update ensures that leave allocation calculations use a consistent UTC date, preventing incorrect leave limits from being reported. This fix improves the reliability of our leave management system.
Original PR description
Issue: ----------------------------------- At certain times of the day (e.g., around midnight UTC), the test would fail deterministically ``` test_allocation_stats_with_duplicate_leave_type_names…
Issue:
-----------------------------------
At certain times of the day (e.g., around midnight UTC), the test would fail deterministically
```
test_allocation_stats_with_duplicate_leave_type_names
self.assertEqual(leave_type_no_comp.with_context(employee_id=employee_id).max_leaves, 10)
AssertionError: 0.0 != 10
```
Cause:
-----------------------------------
This occurred due to a timezone mismatch during the test execution. When creating the `hr.leave.allocation`, `date_from` implicitly defaults to `fields.Date.context_today(self)` (which evaluates the date based on the test user's timezone, e.g., Europe/Brussels). However, the `max_leaves` computation in `hr.leave.type` evaluates valid allocations using `fields.Date.today()` as the target date (which strictly evaluates to the UTC date)
At certain times of day, this caused the allocation's `date_from` to evaluate to 'tomorrow' relative to the UTC `target_date`. Because the allocation was technically in the future relative to UTC, it was skipped during the computation causing `max_leaves` to return 0.0 instead of 10.
Solution:
-----------------------------------
Explicitly define `'date_from': date.today()` when creating the allocation in the test case. This perfectly aligns the allocation's starting date with the strict UTC evaluation used by the `max_leaves` computation under the hood.
Runbot Error: [937759](https://runbot.odoo.com/odoo/runbot.build.error/937759)
Related PR: https://github.com/odoo/odoo/pull/261680This update fixes an issue where Swiss payroll tax calculations were incorrect. The change removes a technical setting that was incorrectly treating taxes as 'excluded' for Swiss payslips, ensuring accurate tax reporting in accordance with Swiss regulations. This improves the reliability of payroll processing for Swiss companies.
Original PR description
Steps to reproduce: ---------------------------------------- - Install the l10N_ch localization. - Create an 8.1% purchase tax (tax included). - Add the tax created in step 2 to the credit account in…
Steps to reproduce: ---------------------------------------- - Install the l10N_ch localization. - Create an 8.1% purchase tax (tax included). - Add the tax created in step 2 to the credit account in wage type 1910. - Create an employee in the Swiss company and create a certificate type in the wage statement tabulation of the employee record. - Create a contract for the employee created in step 4. - Ensure that wage type 1910 is present in the contract created in step 5 and set the contract's status to 'Running'. - Generate a new payslip for the employee created in step 4. - Compute the sheet and create the draft entry. - The tax amount is not calculated correctly. Cause: ---------------------------------------- In Swiss payslips taxes are always computed as excluded because of [`_prepare_product_base_line_for_taxes_computation()`](https://github.com/odoo/odoo/blob/30b525062fee48a453162e4f8087000b3c7dcd24/addons/account/models/account_move.py#L1510). Solution: ---------------------------------------- Override `_prepare_product_base_line_for_taxes_computation` and remove the special mode. opw-4997536
This fix ensures that website customers correctly inherit the intended pricelist when created. Previously, the system incorrectly reverted to the global default pricelist. The update adjusts how the system determines the pricelist based on website context, resolving this issue and improving price accuracy for website users.
Original PR description
Steps to reproduce: =================== 1. Create 2 pricelists, pricelist 1 is backend-only (no website_id, not selectable), pricelists 2 have website_id set 2. Create a website form creating a…
Steps to reproduce: =================== 1. Create 2 pricelists, pricelist 1 is backend-only (no website_id, not selectable), pricelists 2 have website_id set 2. Create a website form creating a customer with a pricelist field 3. Submit the form selecting pricelist 2 (first website-available one) => Pricelist reverts to pricelist 1 (the global default) Cause: ====== When creating a partner via a website form with a specific pricelist, the inverse of `property_product_pricelist` calls `_get_country_pricelist_multi` to determine the "default" pricelist and decide whether to store the value explicitly or store False (meaning "use the default"). With `website_sale` installed, the search domain hook adds website-availability filtering during website requests. This causes the inverse to compute a different "default" pricelist than what the compute uses outside the website context. The inverse sees pricelist 2 as the "website default" (first by sequence matching the website domain) and stores False. The compute later runs without website context, finds pricelist 1 as the global default, and returns the wrong value. Solution: ========= The fix bypasses website filtering in the search domain hook when called from the inverse, ensuring the stored value is based on the context-independent default. opw-6092161 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where unit prices displayed on invoices and quotations were showing excessive decimal places when using fiscal position remapping (e.g., EU intra B2B). The fix ensures prices are rounded to the correct currency precision, maintaining accurate fiscal calculations and improving data consistency. This impacts sales pricing and reporting accuracy.
Original PR description
**problem:** When taxes are configured as tax-included and a fiscal position remaps them (for example from NL 21% ST to EU intra B2B 0% EX EU G), the computed unit price is stored with excessive…
**problem:** When taxes are configured as tax-included and a fiscal position remaps them (for example from NL 21% ST to EU intra B2B 0% EX EU G), the computed unit price is stored with excessive decimal digits (e.g 82.644628099...) **steps to reproduce:** 1. Install `l10n_nl` 2. Switch to the Dutch company/ NL company 3. Ensure fiscal position `EU intra B2B` maps `21% ST` to `0% EX EU G` 4. Set tax `21% ST` as tax included 5. Create a product with sales tax `21% ST` 6. Create a quotation/invoice, apply fiscal position `EU intra B2B` 7. Add the product line (or change fiscal position on an existing line and update taxes) 8. You will see `price_unit` displays too many decimals **cause:** In both `sale.order.line._reset_price_unit` and `account.move.line._compute_price_unit` unit prices coming from tax-included remapping are written directly to price_unit. https://github.com/odoo/odoo/blob/7302b504fc03583944f4dff947cf9725fec9a75b/addons/sale/models/sale_order_line.py#L598-L602 https://github.com/odoo/odoo/blob/7302b504fc03583944f4dff947cf9725fec9a75b/addons/account/models/account_move_line.py#L871-L878 The tax remapping path uses tax detail computations with 'global' rounding to preserve fiscal accuracy during conversion, but the resulting `price_unit` was written back without currency rounding. https://github.com/odoo/odoo/blob/7302b504fc03583944f4dff947cf9725fec9a75b/addons/account/models/account_tax.py#L1303-L1310 **fix:** - Round computed `price_unit` with document currency precision before storing in both sale_order_line, account_move_line. - In `account.move.action_update_fpos_values`, recompute from untaxed base when tax include mode changes, then round with currency precision. (We do this change to ensure behavior is consistent, when changing fiscal position and clicking "update taxes" on already existent quotations/invoices" opw-6081856 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a limitation in the accounting settings where the 'Deferred Expense' field only showed current asset accounts. Now, it correctly includes prepayment accounts, ensuring users can accurately categorize deferred expenses. This improves the accuracy of financial reporting and simplifies expense tracking.
Original PR description
Problem: The deferred expense account field only allowed to select from current asset accounts, but it should also allow prepayment accounts. Steps to reproduce: 1. Install Accounting app 2. Go to Accounting > Configuration > Settings 3. In the "Deferred expense" section, try to select an account in the "Deferred expense" field and see that only current asset accounts are available. Cause: The domain on the deferred expense account field only included current asset accounts. opw-6134576
This update resolves a technical issue where a test was incorrectly marked as commented instead of updated in the recent code changes. The fix ensures that the test is properly updated, maintaining the integrity of the Belgian Coda integration for financial reporting. This prevents potential disruptions to the accounting process.
Original PR description
Test was commented instead of updated in this commit https://github.com/odoo/enterprise/commit/f1fafe0060c221e4a268c897af30455cc3d029ef task-none
This update prevents branch companies from being incorrectly designated as payment providers. Previously, a configuration issue allowed branch companies to use payment providers set up in the parent company, which could cause accounting discrepancies. This fix ensures proper account journal management and prevents potential errors during payment processing.
Original PR description
Issue: --- Branch companies can be selected as payment provider company, which should be restricted due to the limitation on account jounral. Steps to reproduce: 1- Create a branch company. 2- Add a website to the branch company. 3- Enable a payment provider in the parent company. 4- Duplicate the provider for the branch company and set branch as the company. 5- Navigate to the shop and add a product to cart. 6- Checkout and pay. In the SO, you can check that the payment provider from parent is used. Cause: --- This is introduced after https://github.com/odoo/odoo/commit/b093786714e9e8567cf75abf78ac3d954a3d89b2. That fix ensures providers from parent company to be returned as the branch compatible provider. However, that fix didn't restrict the branch companies to be selected as provider company which we shouldn't allow. #263869 opw-6013978 Forward-Port-Of: odoo/odoo#257622
This update ensures that when you refresh a timesheet record after searching, the correct, specialized form view is displayed. Previously, a generic form view was shown, causing confusion. This fix guarantees a smooth and accurate experience when managing timesheets.
Original PR description
…m view * Go to Timesheets > My Timesheets > switch to Grid view. * Hover over a cell with a timesheet entry and click the magnifier (search) icon. * The list opens; click a record to open its form view. * Observe the URL: `/odoo/timesheets/account.analytic.line/<id>`. * Refresh the page (F5). Before this commit, the generic form view was shown instead of the timesheet-specific form view. This occurred because, when reloading a page with a dynamic action and a resId, a generic view layout [false, "form"] was requested instead of the action-defined view. Now, the dynamic action is properly restored on refresh, ensuring the correct specific view is loaded for the form. opw-6133602
This update fixes an issue where fixed taxes weren't correctly excluded from global discounts in the POS system. Previously, applying a discount reduced the total amount, which is now corrected to accurately reflect the tax structure. This ensures accurate order totals and improved the POS discount functionality.
Original PR description
When applying a global discount, the amount of fixed taxe was reduced by that disocunt. This is not correct for fixed amount taxes. Steps to reproduce: ------------------- * Enable global discount * Configure a fixed-amount tax and a regular percentage tax (e.g. VAT) on the same product. * In POS, add this product to an order. * Apply a global discount > Observation: Total is not correct. Why the fix: ------------ Only taxes that accountTaxHelpers.can_be_discounted allows (mirroring account.tax._can_be_discounted, i.e. not fixed or code) are linked on the global discount line. The discount product line is excluded from lines considered for the global discount base. opw-6138507
This update resolves a technical issue preventing Viva payments in the POS kiosk. The Viva payment system required a unique 'cashRegisterId' in the payment request, which was previously missing. The fix ensures this ID is automatically generated from the cashier's name, guaranteeing successful payment processing with Viva.
Original PR description
When validating a payment in POS Kiosk with Viva payment method we get a Viva.com error Viva’s card-terminal API validates the JSON body with Pydantic and requires a non-empty ``cashRegisterId``. Steps to reproduce: ------------------- * Open POS in kiosk * Make an order and pay with Viva > Observation: Viva returns a validation error: ``cashRegisterId`` is missing or required in the request body (Pydantic ``missing`` on ``body.cashRegisterId``). Why the fix: ------------ Compute ``cashRegisterId`` in the POS client as cashier name, then ``pos.config.name`` so the value is always a non-empty string sent to ``viva_wallet_send_payment_request``. opw-6091223
This update optimizes the process of exporting large datasets (like invoices or sales records) to XLSX or CSV files. Previously, the system loaded all records at once, leading to memory issues. Now, data is processed in batches, reducing memory usage and improving export speeds.
Original PR description
When exporting a number N of records as XLSX or CSV file, we call the export_data() method for the N records at the same time. This method prefetches the selected fields for all the records which can lead to memory limit errors when N is too large. We propose to batch this call and invalidate the recordsets between batches. Benchmarks ----------- Execution time: | No records | Before PR | After PR | |------------|-----------|----------| | 70 260 | 3.82 s | 3.94 s | | 228 116 | 18.71 s | 19.36 s | | 394 381 | 31.02 s | 32.67 s | Memory usage: | No records | Before PR | After PR | |------------|-----------|----------| | 70 260 | 316.0 MB | 273.5 MB | | 228 116 | 796.9 MB | 620.8 MB | | 394 381 | 1.3 GB | 947.7 MB | opw-5881026 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes an issue where by-products weren't being correctly tracked during Manufacturing Order validation. Previously, the system reset by-product quantities to their original values, leading to inaccurate production records. This change ensures by-products are accurately reflected in the MO's output.
Original PR description
Backport of:
- https://github.com/odoo/odoo/commit/1dac720a74547e7120d14733c7abda81e959fb3c
- https://github.com/odoo/odoo/commit/7e21cb9befae0e9ce1eabafc2d5366de5097547c
Steps to reproduce:
- Create a product P1 with the Follwing BoM:
- 1 component C1 (10 units)
- 1 by-product BP1 (10 units)
- Create a Manufacturing Order for 1 unit of P1 and confirm it
- Set quantity to 5 units for C1 and 5 units for BP1
- Set Consumed = True for C1 and Produced = True for BP1
- Validate the MO
Problem:
C1 is correctly validated with 5 units, but BP1 is reset to 10 units
_onchange_quantity only checks raw_material_production_id to set `manual_consumption = True`, so by-products (which use production_id) never get `manual_consumption` set. As a result, `_set_qty_producing` does not skip the by-product move and resets its quantity to the product_uom_qty on validation.
opw-6221482This update allows users to re-submit invoices that were previously rejected by the Romanian tax authority (SPV). Previously, rejected invoices were deleted and recreated, losing important tracking information. Now, rejected invoices are preserved as a history, improving traceability and simplifying the process of resolving issues with the SPV.
Original PR description
Allow users to re-send invoices that were rejected by the SPV. Previously, EDI documents were deleted and recreated on every interaction, losing history in the process. This commit updates existing EDI documents in place instead, preserving failed documents as history for traceability. task-[5976612](https://www.odoo.com/odoo/project/967/tasks/5976612) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update ensures all date displays in the Point of Sale module consistently use Odoo's standard format. Previously, dates were displayed based on the user's device, leading to potential inconsistencies. This change improves clarity and accuracy for sales reports and receipt printing.
Original PR description
Why this commit: --- There are two instances in version 17.0 where dates use toLocaleString(), which relies on the device's local format instead of the Odoo-configured format. Since Odoo already…
Why this commit: --- There are two instances in version 17.0 where dates use toLocaleString(), which relies on the device's local format instead of the Odoo-configured format. Since Odoo already defines a standard date format, all toLocaleString() usages in pos should be replaced to ensure consistency. Starting from version 17.0, cash in/out receipts and the sales report use the local device time format. This commit updates those references and aligns them with the Odoo-configured date format. During forwardporting the fix in version 19.0 needs to be added to [base.js](https://github.com/odoo/odoo/blob/0352c5e8543b75083cf555c3d5b4f164f949b465/addons/point_of_sale/static/src/app/models/related_models/base.js#L64-L69). As formatDateOrTime function is used in the [reciept header](https://github.com/odoo/odoo/blob/0352c5e8543b75083cf555c3d5b4f164f949b465/addons/point_of_sale/static/src/app/screens/receipt_screen/receipt/receipt_header/receipt_header.xml#L13) printing date on all reciepts. After this commit: --- <img width="947" height="982" alt="image" src="https://github.com/user-attachments/assets/2d9e4199-75dd-40ea-aeb1-27401c9022f3" /> All date references consistently use the Odoo-configured date format. OPW: 6087341 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259112
This update fixes a bug that allowed users to add a product template as an optional product on itself during import. This caused errors when creating sales orders. The change restricts the system to prevent this scenario, ensuring data integrity and preventing order creation issues.
Original PR description
Issue: --- Due to this issue, a product template can be added as an optional product on itself by using import feature. Steps to reproduce: 1- Import a product using sheets. 2- Re-import it again and this time set `optional_product_ids` the same value as `external_id` in the sheet. 3- Navigate to the product template form and you can see the same product template is added to optional products of the product template. If you create a SO using the product, an error will be raised. This can be prevented by a domain restricting to set this product as optional products. opw-6150049
This update resolves an error that occurred when users removed the date field in the Accrued Expense Entry wizard. The fix adds a check to ensure the date field has a valid value before performing comparisons, preventing a type error. This ensures the Accrued Expense Entry functionality remains stable and reliable.
Original PR description
Currently, error occurs when user removes date on Accrued Expense Entry wizard. Steps to replicate: - Install `purchase` and `accountant` with demo. - Open any Purchase Order > Click on cog menu >…
Currently, error occurs when user removes date on Accrued Expense Entry wizard.
Steps to replicate:
- Install `purchase` and `accountant` with demo.
- Open any Purchase Order > Click on cog menu > Accrued Expense Entry.
- Remove value from `date` and click else where.
Error:
```
File '/home/odoo/odoo19/community/addons/account/wizard/accrued_orders.py', line 67, in _compute_reversal_date
if not record.reversal_date or record.reversal_date <= record.date:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '<=' not supported between instances of 'datetime.date' and 'bool'
```
Cause:
- As the user removed value from `date`, [here] `record.date` is received as False.
- As a result the comparison `record.reversal_date <= record.date` causes this error to occur.
Solution:
- Added a conditional check for `date` before the date comparison.
[here]: https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/account/wizard/accrued_orders.py#L67
No ID
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update fixes an issue where extra prices on combo products weren't correctly converted to the sale order's currency, leading to inaccurate totals. The change ensures that extra prices are properly converted, resulting in accurate pricing calculations for sales orders using different currencies. This improves the reliability of sales order pricing.
Original PR description
The total of a sale order containing a combo product that has an extra price is not correclty converted to the sale order's pricelist currency Steps to reproduce: 1. Install Sales 2. Go to Invoicing…
The total of a sale order containing a combo product that has an extra price is not correclty converted to the sale order's pricelist currency Steps to reproduce: 1. Install Sales 2. Go to Invoicing > Configuration > Accounting > Currencies and activate currency MXN 3. Go to Sales > Products > Pricelists and create a new pricelist for currency MXN 4. Go to Sales > Products and create a new combo product "test" 5. Create a combo choice "combo" with options "Large Cabinet" and extra price 10000$ 6. Go to Sales and create a new quotation for customer Acme Corporation with product "test" (total is $10,001) 7. Change the pricelist to MXN and update prices 8. The total is ~MX$10,018 (it should be ~MX$186,682) Issue: The extra price of a combo product is not converted to the sale order's pricelist currency, so we end up adding the price of the product in the order's currency with the extra price not converted Solution: Convert the extra price of the combo product to the sale order's pricelist currency opw-6192935
This update resolves an issue where the generic tax report wouldn't display an error when the reported net value was negative. The fix ensures that the report accurately checks for discrepancies in tax amounts, even with negative balances, preventing misleading results.
Original PR description
**Issue:** In the generic tax report, a check is performed on the report lines to ensure that the declared tax amount is consistent with the expected amount. If the difference between the declared tax amount and the expected one is higher than 0.1% of the declared net amount, then a error message is displayed. If the net amount is negative, the error message is never displayed because the computed percentage of the tax difference is negative and therefore lower than 0.1% (i.e. 0.001). opw-6014350
This update fixes a bug where adding serial numbers to outgoing picking when the quantity is zero could lead to incorrect quantity counts. Now, only the manually added serial numbers are correctly applied, ensuring accurate tracking of stock movements. This prevents discrepancies between the number of serial numbers and the actual quantity shipped.
Original PR description
**Problem**: When we set the quantity of a move to zero, then add serial numbers manually, if the serial numbers are not the first ones in the list of available serial numbers, The first few…
**Problem**: When we set the quantity of a move to zero, then add serial numbers manually, if the serial numbers are not the first ones in the list of available serial numbers, The first few available serial numbers will be added to the move, which causes a mismatch of quantity and the number of serial numbers. **Before this commit:** If we have three serial number SN-001, SN-002, SN-003 created in order, and we set the quantity of the move to zero, then add SN-002 and SN-003 manually, SN-001 will be added automatically while saving. **After this commit:** Only SN-002 and SN-003 will be added to the move, which matches the quantity. **Steps to reproduce:** 1. Create a product with tracking by unique serial number, and create 3 lots SN-001, SN-002, SN-003 for this product. 2. Create a picking and add a move for this product, set the demand to 3 and quantity to 0. 3. Set the quantity to 2, and add SN-002 and SN-003 to the move, then save the picking. 4. SN-001 will be added to the move automatically, but the quantity stays at 2. opw-6121208
This update resolves an issue where the chatter section was hidden on the Documents mobile Kanban view. The fix adjusts CSS styling to ensure the chatter is always visible and accessible, improving usability for mobile users. This prevents a frustrating user experience when accessing document information.
Original PR description
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not…
**Steps to reproduce:** - Go to Documents app in mobile - Go to the kanban view - Add some files and select one - Click on `Info & Tags` button in the control panel - Reload the page - Chatter is not displayed but the button is still enabled - Switching to the list view properly shows it **Issue:** We have two conflicting css styling on mobile: - `overflow-hidden` was added for mobile to avoid multiple scroll bars - `min-height: 100%` which is due to the default `o_kanban_ungrouped` in the controller css This means that the element is present at the bottom of the page, but we can't get to it manually. When re-enabling the action we are properly moved to the existing chatter (but we can't go back to the top). Also the documents panel should have a single scrollbar to display all the records, but we still need a way to scroll the messages of the chatter. **Fix:** Set `min-height: 0;` for documents kanban to ensure the chatter is still visible and accessible on mobile by default. This makes the chatter take the full available height when displayed. original overflow fix: https://github.com/odoo/enterprise/commit/945b9e2b1c6752bd905695aa40b0babcf38c50cd opw-6061993