Daily updates from Odoo
Wednesday, June 10, 2026
275 changes
27 changes
Resolved issues and error corrections
This update resolves an issue where the 'Add to Cart' button wasn't functioning correctly for alternative products on the website. The fix ensures that users can successfully add these alternative products to their cart, improving the shopping experience. The change was made to correctly identify the button element within the website's product display.
Original PR description
Steps to reproduce: --- - Install `website_sale`. - Create a product and from the Sales tab, add alternative products, making sure all products are published on the website. - Open the main product…
Steps to reproduce: --- - Install `website_sale`. - Create a product and from the Sales tab, add alternative products, making sure all products are published on the website. - Open the main product on the website. - In the alternative products section, open the editor, click the `brush` icon under `card design`. - Under Actions > Buttons, click on the `cart` icon. - Save the changes and click the `Add to Cart` button on an alternative product. Issue: --- - Clicking the `Add to Cart` button on alternative products does nothing. Root cause: --- - At [1], the `AddToCart` interaction uses the selector `.oe_website_sale button[name="add_to_cart"]` to find and attach click handlers. When the dynamic snippet renders alternative products, `startInteractions` is called on the `.dynamic_snippet_template` div. It searches for the button inside that div, but at [2], no element wrapping the button has the `oe_website_sale` class in the rendered product card template. So the selector matches nothing, and no click handler is attached. Fix: --- - Add `oe_website_sale` to the `o_wsale_product_btn` wrapper div in the product card template so the button becomes a descendant of `.oe_website_sale` within the injected content, allowing the interaction to attach correctly. [1]https://github.com/odoo/odoo/blob/cbc446bfcaeeb4787cb512ddffbbeb2a154a6dde/addons/website_sale/static/src/interactions/add_to_cart.js#L5 [2]https://github.com/odoo/odoo/blob/cbc446bfcaeeb4787cb512ddffbbeb2a154a6dde/addons/website_sale/templates/snippets/product_snippet_template_data.xml#L95-L113 opw-6197375 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263253
This update ensures that descriptions are correctly populated on sales order lines when adding delivery items. Previously, only the product name was used, leading to incomplete order details. This fix maintains consistent and accurate product descriptions across all order stages, improving order clarity and reporting.
Original PR description
When a line is added to a delivery related to a sale order, the corresponding line created in the sale order uses only the display_name as a description. This commit makes sure that if a previous SO line exists for the product, the new line uses the same description. Otherwise we call `get_product_multiline_description_sale()` Steps to reproduce: - Create a product with a description in the Sales tab - Create a quotation with any product (can be said product) and confirm it - Go to the delivery action, and add a new line with the product in the view, set delivered quantity to 1 - After Validating, you'll notice that the new line in the Quotation doesn't have a description opw-6175891 Forward-Port-Of: odoo/odoo#267425 Forward-Port-Of: odoo/odoo#262276
This update enhances the SMS account registration process by adding clear error messages to the IAP system. Specifically, it now identifies issues like unsupported countries or inactive database records, providing better guidance to users. This improves the reliability and user experience of the SMS feature.
Original PR description
This commit add some error messages (country_not_supported, not_active_db) received by IAP. Task-6240200 IAP: https://github.com/odoo/iap-apps/pull/1612 Forward-Port-Of: odoo/odoo#267459
This update fixes an issue where the Balance Sheet report export was incorrectly including all accounts instead of the selected one when using the date filter. The fix removes a filtering process that was unintentionally introduced, ensuring the report accurately reflects the user's chosen account selection. This improves the reliability of financial reporting.
Original PR description
Steps: - Open Balance Sheet report and unfold lines - Open the General Ledger from a line with an account - On GL report, change date filter - Export XLSX report -> We export all accounts instead of the one selected in the search bar Cause: Since f8dceec74e44ffe4aef67655be8811c96da91eba we filter out the filter if a default account is defined in the context which is the case in the `caret_option_open_general_ledger` method Fix: Remove the filtering as the behavior that was fixed by the mentioned commit does not happen anymore. opw-6234427 Forward-Port-Of: odoo/enterprise#119588 Forward-Port-Of: odoo/enterprise#119156
This update resolves an issue where the database upgrade process would fail when reloading the Hungarian chart template due to a dependency on the NAV service. The fix bypasses the credential validation step during the migration, allowing upgrades to proceed smoothly without relying on external connectivity.
Original PR description
Steps to Reproduce: * Create a Hungarian company on 19.0 (or earlier). * Configure NAV credentials through Settings. * Upgrade the database to saas~19.2. Issue: * The upgrade fails while reloading…
Steps to Reproduce:
* Create a Hungarian company on 19.0 (or earlier).
* Configure NAV credentials through Settings.
* Upgrade the database to saas~19.2.
Issue:
* The upgrade fails while reloading the Hungarian chart template.
```python3
Traceback (most recent call last):
File "/home/odoo/src/odoo/saas-19.2/odoo/service/server.py", line 1626, in preload_registries
registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update'], reinit_modules=config['reinit'])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/func.py", line 65, in locked
return func(inst, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/registry.py", line 202, in new
load_modules(
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/loading.py", line 502, in load_modules
migrations.migrate_module(package, 'end')
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/migration.py", line 215, in migrate_module
exec_script(self.cr, installed_version, pyfile, pkg.name, stage, version)
File "/home/odoo/src/odoo/saas-19.2/odoo/modules/migration.py", line 253, in exec_script
mod.migrate(cr, installed_version)
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_hu/migrations/3.1/end-migrate_update_taxes.py", line 7, in migrate
env['account.chart.template'].try_loading('hu', company)
File "/home/odoo/src/odoo/saas-19.2/addons/account/models/chart_template.py", line 181, in try_loading
return self._load(template_code, company, install_demo, force_create)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_hu_edi/models/template_hu.py", line 11, in _load
company._l10n_hu_edi_configure_company()
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_hu_edi/models/res_company.py", line 79, in _l10n_hu_edi_configure_company
res_config_id = self.env['res.config.settings'].create({
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/decorators.py", line 363, in create
return method(self, vals_list)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/enterprise/saas-19.2/hr_payroll/models/res_config_settings.py", line 39, in create
return super().create(vals_list)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/odoo/orm/decorators.py", line 363, in create
return method(self, vals_list)
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_hu_edi/models/res_config_settings.py", line 48, in create
record.company_id._l10n_hu_edi_test_credentials()
File "/home/odoo/src/odoo/saas-19.2/addons/l10n_hu_edi/models/res_company.py", line 107, in _l10n_hu_edi_test_credentials
raise UserError(
odoo.exceptions.UserError: Helytelen NAV hitelesítő adatok! Ellenőrizze, hogy a cég adószáma helyesen van-e beállítva.
Hiba részletei: HTTPSConnectionPool(host='api.onlineszamla.nav.gov.hu', port=443): Max retries exceeded with url: /invoiceService/v3/tokenExchange (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x798a970f1fd0>: Failed to establish a new connection: [Errno 111] Connection refused'))
```
Cause:
* Since the introduction of the Hungarian tax migration using `account.chart.template.try_loading('hu', company)` in saas~19.1, upgrades reload the Hungarian chart template.
* When `l10n_hu_edi` is installed, chart template loading triggers `_l10n_hu_edi_configure_company()`, which performs NAV credential validation through `_l10n_hu_edi_test_credentials()`.
* The credential validation performs a live request to the NAV service, making the upgrade dependent on an external service. https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_hu_edi/models/res_company.py#L99-L109 https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_hu_edi/models/template_hu.py#L11
Fix:
* Bypass NAV credential validation during the migration.
* The migration only updates localization data and does not modify the configured EDI credentials.
* This prevents temporary NAV connectivity issues from aborting the upgrade process.
see https://github.com/odoo/odoo/pull/253556
opw-6253523
upg-4326247
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#268178This update fixes a visual issue where the carousel display would become unstable when images were resized or changed. The update uses a new system to automatically adjust carousel item heights, ensuring a smooth and consistent user experience. This prevents layout problems and improves the overall appearance of the website builder.
Original PR description
In a carousel snippet all carousel items keep a consistent height to prevent layout jitter when sliding. The height synchronization was broken in the `s_carousel` snippet when item dimensions were modified via border overlays (padding changes). The issue was caused by the resize event being triggered from a different jQuery instance than the one used to register the height synchronization listener, preventing the handler from being executed. Steps to reproduce (Border Overlay): 1. In the website builder, add the `s_carousel` snippet. 2. Drag the lower border overlay so that the height of an image increases. 3. Navigate through the carousel and observe height changes causing a jitter effect. Task: [5135520](https://www.odoo.com/odoo/project/974/tasks/5135520) Forward-Port-Of: odoo/odoo#268722 Forward-Port-Of: odoo/odoo#265549
This update prevents a disruptive 'Access Error' in the command palette that appeared when users without accounting access attempted to use accounting report commands. The fix ensures that the system gracefully handles access restrictions, improving the user experience. It corrects a technical issue where the system incorrectly displayed an error message instead of simply not offering the command.
Original PR description
…n-accounting users Before this commit, users without accounting access rights would encounter an "Access Error" when typing in the command palette. This occurred because the 'account_report_variants' command provider was registered in the global namespace and unconditionally executed an RPC call to (get_available_variants) as soon as the user typed two or more characters. The backend ACLs correctly blocked this request, but resulted in a disruptive error dialog for the user. This commit fixes the issue by verifying that the user has access to the accounting reports or the acounting app, if they don't it would return an empty list. Steps to reproduce the bug: 1. Log in as admin 2. Go to the Users view 3. Set ESG to 'No' 4. Set Accounting to 'No' 5. Refresh the page 6. Open and use the command palette -> Access Error: You are not allowed to access 'Accounting Report' records. task: 6246337 m
This update ensures that fiscal category and product information is automatically loaded when using the self-order blackbox feature. Previously, this data wasn't consistently available, leading to potential inaccuracies. This change improves the reliability and accuracy of self-order transactions.
Original PR description
Before this commit, the fiscal category and the products work in and work out weren't necessarily automatically loaded when using the self with a blackbox, it is now the case. Forward-Port-Of: odoo/enterprise#117288 Forward-Port-Of: odoo/enterprise#117044
This update fixes an issue where self-order receipts incorrectly displayed 'Service at Table' instead of 'Pickup At Counter' when a customer selected a counter service without identification. This change ensures the receipt accurately reflects the customer's order method, improving clarity and accuracy for both staff and customers. The fix was implemented as part of the standard Odoo development process.
Original PR description
When selecting a preset with a service at counter but without identification, after a self order the receipt header was wrongly showing "Service at Table" instead of "Pickup At Counter". This is now fixed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#264454 Forward-Port-Of: odoo/odoo#264115
This update fixes an issue where Point of Sale account move lines were incorrectly reporting tax base amounts as always positive, regardless of the sale's actual tax impact. This change ensures that tax calculations in POS transactions accurately reflect the tax liability, leading to more precise accounting reports. It resolves a discrepancy in how tax amounts were processed.
Original PR description
Issue: While creating an account move line from POS, the tax_base_amount of tax line is always positive although it might be negative. Steps to reproduce: - with point_of_sale and account_reports - open register - Sale a product with taxes - close register - Go to Accounting -> Tax Report - Switch to current month - On a line click on the tree dots -> Audit Current Behavior: - POS AMLs always have a positive tax base amount for tax lines. Expected behavior: - POS AMLs have a positive or negative base amount for tax lines depending on the move. opw-5975658 Forward-Port-Of: odoo/odoo#265479
This update fixes an issue where untaxed invoice lines were incorrectly inheriting datev code from the previous line in the report. This resulted in inaccurate datev reports, particularly for German companies. The fix ensures that untaxed lines now correctly have an empty datev code, aligning with the expected report format.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update resolves an issue where invoices for Persona Natura customers in Colombia were incorrectly formatted for export to the DIAN tax authority. The fix ensures the correct XML structure is generated, addressing a misinterpretation of customer types and preventing export errors. This ensures accurate tax reporting for Colombian businesses.
Original PR description
Issue: Colombian partner being Persona Natura are misinterpreted as Person Juridica. It raises issue while exporting XMLs for dian. Steps to reproduce: - In a Colombian company - Create a Customer with NIT and "Obligaciones y Responsabilidades" to "R-99-PN" - Create an invoice - Send the invoice Current behavior: - node <cbc:AdditionalAccountID> is set to 1 and node PartyIdentification is missing Expected behavior: - node <cbc:AdditionalAccountID> is set to 2 and there is a PartyIdentification node Cause: Colombian partners having a NIT have is_company to True. However, Persona Natura have NIT but aren't companies. opw-6206308 Forward-Port-Of: odoo/enterprise#118193
This update resolves an error that occurred during DHL delivery confirmations when the scheduled delivery date was missing or set to a past time. The system now automatically sets the delivery date to one hour in the future, preventing the error and ensuring successful order confirmations.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update fixes an issue where the 'Cancel Reason' wasn't properly transmitted when reversing invoices in Peruvian companies. Now, the credit note generated for the reversal accurately includes the user-specified cancellation reason, ensuring compliance with Peruvian tax regulations (SUNAT) and providing complete documentation.
Original PR description
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit…
### Issue before this commit: When reversing an invoice in a Peruvian company, the "Cancel Reason" entered in the credit note window is not propagated to the Peruvian EDI tab of the resulting Credit Note. Only the Credit Reason is successfully reported. ### Steps to reproduce the issue: 1. Download Accounting and l10n_pe 2. Switch to PE company 3. Create an invoice and confirm it 4. Create a credit note for the invoice with a cancel reason and a credit reason and click the reverse button 5. See that in the Peruvian EDI tab only the Credit Reason is reported but not the Cancel Reason ### Cause of the issue: In the l10n_pe_edi module, the override of the _prepare_default_reversal method maps the l10n_pe_edi_refund_reason to the new move's values, but completely omits the mapping of the wizard's textual reason field to the l10n_pe_edi_cancel_reason field of the resulting credit note. ### Reason to introduce the fix: To ensure the generated credit notes contain all required information for the Peruvian EDI (SUNAT). Mapping the cancel reason guarantees that the electronic document accurately reflects both the refund code and the descriptive cancellation text provided by the user. opw-6238525 Forward-Port-Of: odoo/enterprise#119610 Forward-Port-Of: odoo/enterprise#118479
This update fixes an issue where grouped payments were incorrectly linking to unrelated invoices after reconciliation. The process has been updated to ensure payments are accurately associated with the invoices they cover, preventing duplicate payment entries. This improves the accuracy of financial reporting.
Original PR description
Steps to reproduce --- 1. Register a grouped customer payment over several invoices, leaving one of them only partially paid. 2. Register a second grouped payment over two invoices: the partially…
Steps to reproduce --- 1. Register a grouped customer payment over several invoices, leaving one of them only partially paid. 2. Register a second grouped payment over two invoices: the partially paid one and a brand new invoice. 3. Open the first payment, its "Reconciled Invoices" smart button now lists the new invoice from the second payment, which it never paid. Issue --- The smart button is built from the stored `invoice_ids` many2many, which shares its relation table with `account.move.matched_payment_ids`. After reconciling, the register wizard links the payment to its invoices with `lines.move_id.matched_payment_ids += payment` at https://github.com/odoo/odoo/blob/f726393267a28cedd5febd2106de17ae3838f3ff/addons/account/wizard/account_payment_register.py#L1212. When the payment groups several invoices, `lines.move_id` is a multi-record recordset. Reading `matched_payment_ids` on it returns the union of the payments already linked to all those invoices, and `+=` writes that union back to every invoice as a `(6, 0, ...)` replace command. So an invoice already paid by an earlier payment spreads that earlier payment onto every other invoice grouped in the new one, including brand new invoices, which then wrongly appear on the earlier payment. opw-6188013 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267968
This update removes a specific message from invoices sent outside of PEPPOL, which was inappropriate for Business-to-Consumer (B2C) customers. The change ensures that B2C invoices are cleaner and more professional, aligning with customer expectations. This fix was implemented to improve the user experience for B2C transactions.
Original PR description
Currently, if the invoice was not sent through PEPPOL, it is indicated in the mail footer. However, this message is not appropriate for B2C customers. To avoid this, we remove this footer for customers with empty or '/' VAT (B2C). task-6167439 Forward-Port-Of: odoo/odoo#269094 Forward-Port-Of: odoo/odoo#262412
This update corrects a bug where order filters on the Ticket Screen in Point of Sale weren't updating correctly when a different provider state was selected. The fix forces a reload of the Ticket Screen, ensuring that the displayed orders reflect the current state and filters. This prevents outdated order information from being shown to users.
Original PR description
Steps to Reproduce ------------------------- - Install Point of Sale and configure UrbanPiper. - Open a POS session and select a provider state from the notification popup to review orders. - While on the Ticket Screen, select a different provider state to review other orders. Issue ------- - Orders are not updated according to the newly selected state. - Previously applied filters remain unchanged. Cause -------- - Since the user is already on the Ticket Screen, changing only the provider state does not trigger a re-render. - The page was already rendered with the old filters. Fix ---- - The Ticket Screen is first switched away and then re-rendered. - This forces the screen to reload with the updated state and filters. Task: 6079663 Forward-Port-Of: odoo/enterprise#119828 Forward-Port-Of: odoo/enterprise#104546
This update ensures that DATEV customer and supplier export files accurately reflect customer information for non-EU countries like Switzerland. Previously, incorrect fields were populated, but this fix now correctly uses the 'Land' field for these customers, aligning with DATEV's data format requirements and preventing errors in reporting.
Original PR description
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries…
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries For non-EU countries, the `Land` field should be filled instead, and is required whenever the country is not Germany https://developer.datev.de/en/file-format/details/datev-format/format-description/debitorskreditors ### Cause: `_l10n_de_datev_get_partner_list` did not distinguish between EU and non-EU countries As a result, any partner with a VAT number could populate `EU-Land` and `EU-UStID`, even if the country was outside the EU Greece also requires a special case: its VAT prefix is `EL` so the `EU-Land` too, while the country code used in `Land` must remain `GR` ### Steps to reproduce: - Install `l10n_de_reports` and switch to the DE company - Create a customer in Switzerland with a valid VAT number - Create and confirm an invoice for that customer - Go to Accounting → Audit Reports → General Ledger - Select the full year - From the gear menu, export DATEV DATA (zip) - Open the `EXTF_customer_accounts` file ### Before the fix: `EU-Land` and `EU-UStID` are filled for the Swiss customer, while `Land` is empty ### After the fix: `EU-Land` and `EU-UStID` are empty for non-EU countries such as Switzerland, while `Land` is correctly filled `Land` is filled using the following priority: 1. Partner country_code 2. Country extracted from the VAT number 3. Empty opw-5902565 Forward-Port-Of: odoo/enterprise#119780 Forward-Port-Of: odoo/enterprise#113835
This update resolves an issue preventing users in Peru from generating Closing Entries within the tax reporting feature. The fix creates a specific tax report variant for Peru, ensuring accurate VAT calculations and restoring the automated closing account configuration process. This improves the reliability of financial reporting for Peruvian businesses.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must precede the end time for a valid shift template. This ensures users receive clear and helpful guidance.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
This update resolves a crash in the payslip PDF report that occurred when employees didn't have a bank account configured. The fix adds a simple check to ensure the bank account section is only displayed if an employee actually has a linked bank account, improving report stability and preventing errors.
Original PR description
The payslip PDF report crashed when the employee had no bank account configured because the template tried to access bank_account_ids[0] unconditionally. Add a t-if guard on the bank account div to only render it when the employee has at least one bank account linked. Forward-Port-Of: odoo/enterprise#115893
Previously, a sign request scheduled for the future would immediately show up on the portal for the signer. This fix corrects a technical issue where the system wasn't properly recognizing scheduled requests. Now, scheduled requests will only appear on the portal after the scheduled date, ensuring a smoother user experience.
Original PR description
## Issue When scheduling a sign request, the request appears immediately on the portal for the requested signer. ## Steps to reproduce 1. Install *Sign* (`sign`) 2. Create and send a sign request -…
## Issue
When scheduling a sign request, the request appears immediately on the portal for the requested signer.
## Steps to reproduce
1. Install *Sign* (`sign`)
2. Create and send a sign request
- Signer 1: Any portal user (e.g., Joel Willis)
- Use the clock icon to schedule the signature request to a future date
3. Log in as the portal user used in step 2
4. Navigate to Signature Requests
5. **The signature request already appears in the list, even though it was scheduled for a future date.**
## Cause
The portal filters the sign requests shown based on the `is_mail_sent` field, which does not properly reflect when the signature request is shared to the user.
https://github.com/odoo/enterprise/blob/9898272f17809decf6c5bb4600aca46f9ffae6f0/sign/controllers/portal.py#L40
In fact, when scheduling a signature request, the `is_mail_sent` field is unconditionally set to `True`, even if the signature request will only be sent later.
https://github.com/odoo/enterprise/blob/9898272f17809decf6c5bb4600aca46f9ffae6f0/sign/models/sign_request_item.py#L289
## Fix
Since the `"scheduled"` `sign_request_item.state` option introduced by https://github.com/odoo/enterprise/commit/ed8d5a653e01b1378f0020e2f7a7c2d39fadf3e9 in 19.1, we can easily filter out the sign request items that are scheduled. That state is automatically updated by the `_cron_update_state`, introduced by the same commit as the `"scheduled"` option.
https://github.com/odoo/enterprise/blob/9898272f17809decf6c5bb4600aca46f9ffae6f0/sign/models/sign_request.py#L493-L503
opw-6227472
Forward-Port-Of: odoo/enterprise#118491This update fixes an issue where self-order kiosk payments would remain stuck if a user clicked the back button. Now, a confirmation dialog appears, allowing users to cancel the payment before returning to the previous screen. This ensures a smoother and more reliable payment experience for self-order transactions.
Original PR description
Before this commit, when a cash machine payment was in progress in the self order kiosk, clicking the back button would not cause the payment to be cancelled, leaving the cash machine stuck. After this commit, upon clicking the back button a dialog shows asking the user if they want to cancel their payment, and if so the transaction is cancelled before sending the user back. task-6276665 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update significantly speeds up the process of adding and removing participants from marketing campaigns. By optimizing the underlying code, the sync time has been reduced from over 51 seconds to just 0.65 seconds, even with a large campaign of 115,000 participants. This improves the overall performance and responsiveness of the marketing automation features.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update fixes an issue where payslips weren't correctly generating worked day lines for employees using attendance-based work schedules. The change ensures that all employees, regardless of their flexible working arrangement, receive accurate wage calculations based on their attendance records. This improves payroll accuracy and reporting.
Original PR description
### **Steps to reproduce:** - Install Payroll and Attendance apps. - Create an employee with a flexible working schedule and work entry source as attendance. - Create an attendance record for this…
### **Steps to reproduce:** - Install Payroll and Attendance apps. - Create an employee with a flexible working schedule and work entry source as attendance. - Create an attendance record for this employee. - Create and compute a payslip for this employee. ### **Observed Behavior:** Worked Day lines are not generated, and Basic Wage is calculated as 0. ### **Expected Behavior:** Worked Day lines should be populated based on attendance records. ### **Root Cause:** During payslip computation, [_compute_worked_days_line_ids](https://github.com/odoo/enterprise/blob/4339010eb1e1633a67573d08e032f3922b0bec49/hr_payroll/models/hr_payslip.py#L1846) only generated work entries for versions having a `resource_calendar_id` at [1]. As a result, fully flexible employees without a working schedule were excluded from work entry generation, preventing worked day lines from being computed. [1]- https://github.com/odoo/enterprise/blob/4339010eb1e1633a67573d08e032f3922b0bec49/hr_payroll/models/hr_payslip.py#L1890-L1898 ### **Fix:** Remove the `resource_calendar_id` filter when calling `generate_work_entries` in `_compute_worked_days_line_ids` so work entries are also generated for fully flexible employees using attendance-based work entries. **opw-6146452** Forward-Port-Of: odoo/enterprise#117409
A recent test was failing due to a minor issue with how content snippets were being dropped onto the website builder. This fix ensures snippets are consistently placed in the correct dropzone, resolving the test failure and improving the stability of the website builder functionality. The change is a simple correction to the test setup.
Original PR description
Test that was testing that we cannot drop some snippets in a table of content sometimes failed due to the fact that it could sometimes drop in the wrong drop zone. This happens because 2 dropzones are really close to each other: <--- dropzone ---> [1] <--- toc start ---> <--- dropzone ---> [2] <--- section ---> <--- dropzone ---> [3] ... <--- toc end ---> When we move the snippet thumbnail to the dropzone [2], and drop it by calling `getDragHelper` it recomputes the position of the thumbnail, and sometimes it may drop the snippet in the first dropzone [1], breaking the test flow. We fix it by moving the snippet to the third dropzone [3], where it surely will drop, as there are no neighboring dropzones. runbot-241922 Forward-Port-Of: odoo/odoo#268473
This update clarifies the reporting of employee hours by renaming a confusing column from "Expected Hours" and "Theoretical Hours" to "regular hours". This change ensures that the report accurately reflects the hours an employee is scheduled to work, improving data understanding and reporting accuracy.
Original PR description
The column name "Expected Hours" and "Theoretical Hours" is confusing since it doesn't show the hours that the employee is supposed to work according to their contract, just the number of hours that are not considered overtime. This commit renames the column to better reflect the measure that is shown. task-6123642 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#262230
17 changes
Resolved issues and error corrections
This update resolves an issue where the system previously restricted searches using record IDs to only positive numbers. During database migrations, negative IDs could occur. This change allows the system to correctly handle negative IDs, ensuring broader record search capabilities. This improves data accessibility and reliability.
Original PR description
Currently, the validation for the name_service only allows us to search on records with ids greater than or equal to one but in some edge cases like migrations where databases needed to be merged, we ended up with negative ids (v6.0 migration on odoo.com). The ORM is capable of handling these so we allow it in the name_service as well. opw-6213802
This update fixes an issue where DATEV export files incorrectly included EU-specific fields for customers outside the European Union. The change ensures that the correct country code (`Land`) is used for non-EU partners, aligning with DATEV's data format requirements and preventing inaccurate reporting. This improves data consistency and compliance.
Original PR description
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries…
### Issue: In DATEV customer and supplier exports, partners outside the European Union still had the `EU-Land` and `EU-UStID` fields filled However, these fields must only be used for EU countries For non-EU countries, the `Land` field should be filled instead, and is required whenever the country is not Germany https://developer.datev.de/en/file-format/details/datev-format/format-description/debitorskreditors ### Cause: `_l10n_de_datev_get_partner_list` did not distinguish between EU and non-EU countries As a result, any partner with a VAT number could populate `EU-Land` and `EU-UStID`, even if the country was outside the EU Greece also requires a special case: its VAT prefix is `EL` so the `EU-Land` too, while the country code used in `Land` must remain `GR` ### Steps to reproduce: - Install `l10n_de_reports` and switch to the DE company - Create a customer in Switzerland with a valid VAT number - Create and confirm an invoice for that customer - Go to Accounting → Audit Reports → General Ledger - Select the full year - From the gear menu, export DATEV DATA (zip) - Open the `EXTF_customer_accounts` file ### Before the fix: `EU-Land` and `EU-UStID` are filled for the Swiss customer, while `Land` is empty ### After the fix: `EU-Land` and `EU-UStID` are empty for non-EU countries such as Switzerland, while `Land` is correctly filled `Land` is filled using the following priority: 1. Partner country_code 2. Country extracted from the VAT number 3. Empty opw-5902565 Forward-Port-Of: odoo/enterprise#119780 Forward-Port-Of: odoo/enterprise#113835
This update resolves an issue preventing users in Peru from generating closing entries for their tax reports. The fix introduces a dedicated Peruvian tax report variant, ensuring accurate VAT calculations and restoring the automated closing account configuration process. This improves the reliability of the Peruvian accounting workflow.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must precede the end time, ensuring correct shift template creation. This improves usability for users.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
This fix resolves an issue where credit notes for returned dropshipped products incorrectly displayed the wrong lot number on invoices. The update ensures that the correct lot number (the returned one) is shown, improving accuracy and transparency in financial reporting for dropshipping transactions.
Original PR description
**Issue** Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing a credit note for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print -> The generated PDF displays "lot1" instead of "lot2"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 1` since the credit is on a quantity of 1 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80 which would make it as -1 (since `qties_per_lot[sml.lot_id]` is 0 for the first iteration of `sml.lot_id`). Thus, it does not pass by this code (since quantity is greater than 0): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L87-L90 which would make it as 0.
- for the last one, `is_stock_return = False` as it should be, thus the quantity is 1 as it should be. The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 0, lot2: 1}`
The report then selects the first matching lot and stops: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6230281
Forward-Port-Of: odoo/odoo#266716A test was failing due to a minor issue with how content snippets were dropped into a website feature. This update corrects the placement logic, ensuring snippets are reliably added to the intended location, preventing test failures. This improves the stability and reliability of the website content editor.
Original PR description
Test that was testing that we cannot drop some snippets in a table of content sometimes failed due to the fact that it could sometimes drop in the wrong drop zone. This happens because 2 dropzones are really close to each other: <--- dropzone ---> [1] <--- toc start ---> <--- dropzone ---> [2] <--- section ---> <--- dropzone ---> [3] ... <--- toc end ---> When we move the snippet thumbnail to the dropzone [2], and drop it by calling `getDragHelper` it recomputes the position of the thumbnail, and sometimes it may drop the snippet in the first dropzone [1], breaking the test flow. We fix it by moving the snippet to the third dropzone [3], where it surely will drop, as there are no neighboring dropzones. runbot-241922 Forward-Port-Of: odoo/odoo#268473
This update resolves an issue where employees with overlapping contracts would incorrectly receive a 'Duplicate Payslip' warning. The change limits the warning check to only consider payslips with the same version, ensuring more accurate payroll processing. This improves the user experience and prevents unnecessary alerts.
Original PR description
If an employee has a contract that ends in the middle of the month and another contract starts in the same month, the two payslips that are created for the month trigger the "Duplicate Payslip" warning, even though they use different version IDs. This commit limits the search domain for the duplicate payslips to only consider payslips with the same version ID. task-6226391 Forward-Port-Of: odoo/enterprise#118652
This update resolves a performance issue that caused significant lag when hovering over account reports with many columns. The change optimizes CSS styling to reduce unnecessary calculations, resulting in a smoother and faster user experience. This improves the responsiveness of a key business reporting tool.
Original PR description
Forward-Port-Of: odoo/enterprise#119242
This change removes a test that was failing due to inconsistencies in how German date/time formats are handled by Chrome and the underlying Unicode CLDR data. The test was tied to a specific Chrome version and a recent update to the ICU library (which relies on CLDR) has introduced a conflict. This ensures the duration parsing functionality continues to work correctly across different Chrome versions.
Original PR description
Cause: ---------------------------------------- Commit 121806b57816d0fbd48b5538d2a8beae35905d99 added a test verifying that the duration in German is correctly recognized. In the test, "2 Std. 30…
Cause: ---------------------------------------- Commit 121806b57816d0fbd48b5538d2a8beae35905d99 added a test verifying that the duration in German is correctly recognized. In the test, "2 Std. 30 Min. 45 Sek.", was supposed to be recognized as 2.5125 hours. But on some browser versions it fails, as in the latest Chrome version. This is because we use `DurationFormat()` to get the localized units. This method is supported by all browsers and will use the browser's data to get the translations. This data comes from [Unicode CLDR](https://cldr.unicode.org/) which is updated regularly. We would need to change the test depending on the Chrome version, so we just delete it. It appears that for German hours the CLDR definitions have historically shifted between two distinct representations: "Std." and "h" As an example: - CLDR 47: https://github.com/unicode-org/cldr-json/blob/16f6b8578ba5fe98959034706f337674f816fc3f/cldr-json/cldr-units-full/main/de/units.json#L3526-L3527 - CLDR 48: https://github.com/unicode-org/cldr-json/blame/4d06be52b51bb2f75688d0abe55c52a66afed790/cldr-json/cldr-units-full/main/de/units.json#L3916-L3917 So the test fails in CLDR 48 but succeeds in CLDR 47. As the latest version of `ICU` (used by browsers) updates its dependency to CLDR 48 ([src](https://unicode-org.github.io/icu/download/78.html)) this explains why the latest Chrome version makes the test fail. runbot-939543
This update resolves a performance issue within the tests for the 'Discuss' feature. The change optimizes a database query, resulting in faster test execution times. This improvement ensures the stability and responsiveness of the Discuss functionality.
Original PR description
runbot-243772 https://github.com/odoo/enterprise/pull/119886
This update addresses a performance issue within the Odoo Discuss module, specifically related to counting data. The change optimizes a database query, resulting in faster response times and a smoother user experience. This improvement ensures the Discuss feature remains efficient and reliable for all users.
Original PR description
runbot-243772 https://github.com/odoo/odoo/pull/269111
This update fixes an issue where undoing the auto-plan feature would reset a shift's allocated workload hours, leading to inaccurate reporting. The change preserves the original workload value during undo, ensuring that shift allocations remain consistent and reliable. This improves the accuracy of resource planning.
Original PR description
Steps to Reproduce --- 1. Open the Planning module 2. Create an open shift with allocated_hours 3. Click Auto Plan 4. Click Undo on the auto-plan notification Issue --- Undoing an auto-plan operation…
Steps to Reproduce --- 1. Open the Planning module 2. Create an open shift with allocated_hours 3. Click Auto Plan 4. Click Undo on the auto-plan notification Issue --- Undoing an auto-plan operation triggers recomputation of allocated_hours, causing the shift to lose its original workload value. Current Behaviour --- When resource_id is set to False during undo: - _compute_allocated_hours is triggered (depends on resource_id) - _compute_allocated_percentage is triggered (depends on allocated_hours) - Both fields are recalculated, potentially changing allocated_hours from its pre-assignment value Expected Behaviour --- Undoing auto-plan should preserve allocated_hours at its pre-assignment value while allowing allocated_percentage to adapt to the new context (open slot vs assigned resource). Fix --- Use protecting context manager in action_rollback_auto_plan_ids to prevent allocated_hours from being recomputed when resource_id is removed. This allows allocated_percentage to recalculate naturally based on slot duration while keeping allocated_hours stable. task - 4952149 Forward-Port-Of: odoo/enterprise#119772 Forward-Port-Of: odoo/enterprise#102864
This update fixes a login issue in Safari's private browsing mode, where users were unable to complete the turnstile challenge. The fix addresses a conflict between Safari's tracking protection settings and Odoo's form submission process. It ensures a stable login experience for Safari users in private browsing.
Original PR description
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on…
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on Log in Result: nothing happens and there is an error in the console "An invalid form control with name='' is not focusable." Cause: By default Safari has the Settings > Advanced > "Use advanced tracking and fingerprinting protection" set to "in Private Browsing". If this options is enabled in private browser or in all browsing, you can't login to Odoo with turnstile because safari is preventing the update of the element that is preventing to send the form: <input style="display: none;" class="turnstile_captcha_valid" required> When turnstile challenge succeeds, a value should be set to this input that will unlock the form, the .value property is updated but the browser Shadow Content is not (and if we remove display:none, the input is empty). Fix: I've not been able to reproduce the issue without turnstile using same situation and iframe. We don't know Safari heuristic but the unlocking is working if: - we use setProperty instead of .value - we unset required - we remove the input - we display the turnstile_captcha_valid input before challenge This fix replaces setting .value by setProperty, and add a failsafe of unsetting required. opw-5917286 fixes #247536 Forward-Port-Of: odoo/odoo#253367
This update resolves an issue that prevented attendee imports on events with the default mail scheduler. The fix ensures emails are queued instead of processed synchronously, preventing savepoint errors during the import process. This improves the reliability of attendee imports.
Original PR description
Importing attendees on an event that has an `after_sub` mail scheduler (the default on every event) fails with `savepoint "..." does not exist` and the import is aborted.…
Importing attendees on an event that has an `after_sub` mail scheduler (the default on every event) fails with `savepoint "..." does not exist` and the import is aborted. [`_update_mail_schedulers`](https://github.com/odoo/odoo/blob/b2f3270271f6/addons/event/models/event_registration.py#L298) runs the attendee scheduler synchronously on every registration create. The scheduler commits after each mail batch, which is fine from cron but problematic during an import: since [29460b723f49](https://github.com/odoo/odoo/commit/29460b723f49) [`load`](https://github.com/odoo/odoo/blob/b2f3270271f6/odoo/orm/models.py#L884) uses a single savepoint for the whole run, and any commit underneath releases it, so the next `ROLLBACK TO` / `RELEASE SAVEPOINT` raises `InvalidSavepointSpecification`. When `import_file` is in context, trigger the cron like the async path already does so the mails are queued instead of running inline. Steps to reproduce: 0. Have Contacts and Events installed 1. Events > Events, create a published event 2. Open the event, Attendees tab > Favorites > Import records 3. Upload a file with new attendees (Name, Email, no external id) 4. Click Import => "savepoint ... does not exist", import fails Ticket [link](https://www.odoo.com/odoo/project.task/6124741) opw-6124741 Forward-Port-Of: odoo/odoo#267586 Forward-Port-Of: odoo/odoo#260648
This update significantly speeds up the calculation of future leave balances by fixing a recursive process that was causing performance bottlenecks. The change eliminates unnecessary calculations, resulting in a 98% reduction in processing time for complex employee leave scenarios. This improves the responsiveness of the HR module.
Original PR description
## The Problem When computing a future leave balance, `_get_future_leaves_on` triggers `_process_accrual_plans`, which iterates period by period and calls `_get_leaves_taken` at each step.…
## The Problem When computing a future leave balance, `_get_future_leaves_on` triggers `_process_accrual_plans`, which iterates period by period and calls `_get_leaves_taken` at each step. `_get_leaves_taken` re-enters `_get_consumed_leaves` with `ignore_future=True`, but other accrual allocations on the same employee were not guarded by `precomputed_allocations`, causing `_get_future_leaves_on` to fire again for each of them, launching another full accrual run recursively. With N periods and K allocations, total work grew as $O(N^K)$. ## The Solution Adding `not ignore_future` to the guard prevents future projection in any nested context where it is both semantically incorrect and the source of the blowup. --- ## Benchmarks *Tested on a customer database with an employee having 2 accrual allocations and pending future leave requests 6 months out:* | | Queries | Request Time | Improvement | | :--- | :--- | :--- | :--- | | **Before** | 220K | 145.0s | — | | **After** | 2.7K | 2.8s | **-98%** | **Note:** More optimizations could be done to reduce the queries to a constant. However given the current design, it would be a bit big change and the current performance is already acceptable. **OPW-6115804** Forward-Port-Of: odoo/odoo#261172
This update removes a duplicate button from the channel management interface. Previously, users encountered errors when attempting to copy channels, and this feature offered little value. This change simplifies the channel creation process and resolves a technical issue.
Original PR description
duplicating channels does not provide much value. when you try to copy channel error comes like `you do not have enough rights to access the field ai_agent_id on Discussion Channel (discuss.channel).` now we are remove the duplicate button from channels form view cog menu as its does make sense to use it there at all. task-5494736 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269153 Forward-Port-Of: odoo/odoo#268999
This update corrects a bug in the sale details report that previously failed to include discounts applied through loyalty programs. Now, the report accurately displays the total discount amount, including those generated by the loyalty program, ensuring accurate sales reporting. This resolves an issue impacting all users utilizing the loyalty program.
Original PR description
When generating the sale details report, the number of discounts would not include the discount given by a loyalty program. The same problem applies for the total discount amount. Steps to reproduce: ------------------- * Create a loyalty program that gives a 10% discount automatically. * Open the PoS and make an order that activate the loyalty program. * Close the session and open the sale details report for this session. > Observation: The discount number and total is 0 opw-6185554 Forward-Port-Of: odoo/odoo#267753
9 changes
Resolved issues and error corrections
This update corrects a discrepancy in product pricing across Odoo. Previously, changing the price on a product's variant form didn't update the main product template. Now, the system ensures that the sales price is consistently reflected across both the product variant and the main product template, improving data accuracy for sales and inventory management.
Original PR description
Issue: When the sales price is changed from the product variant form for a product without configured variants, the price is updated only on `product.product.lst_price`. The main product form, opened…
Issue: When the sales price is changed from the product variant form for a product without configured variants, the price is updated only on `product.product.lst_price`. The main product form, opened from Inventory > Products, displays `product.template.list_price`, which remains unchanged. The same issue is visible from Purchase Orders because the product internal link on a purchase order line opens `product.product`, while the product page opens `product.template`. Steps to reproduce: - Create or open a product without configured variants - Open product variant form from the internal link in a purchase order - Change the Sales Price on the product from there - Open the product from Inventory > Products (`product.template`) - The template Sales Price still shows the old value Cause: Since version 19.1, `product.product.lst_price` is an editable stored field, allowing variant-level prices to differ from the template price. This is correct for products with multiple variants, where each variant may have its own sales price. However, for products with only one variant (the product itself), no synchronization was performed from `product.product.lst_price` back to `product.template.list_price`, leaving both product forms inconsistent. Solution: - Add `_inverse_product_lst_price` on `product.product.lst_price` so that When `lst_price` is written and the template has exactly one variant, set `list_price` to `lst_price` (delegates to the template) opw-6260015 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update significantly improves the speed of syncing participants to marketing campaigns, particularly for large campaigns. By optimizing the underlying code, the process now takes just a fraction of the previous time (from 51.71 seconds to 0.652 seconds). This enhancement ensures smoother campaign management and reduces potential delays for users.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update fixes an issue where delivery orders weren't correctly reserving newly produced lots in multi-step manufacturing workflows. Specifically, changing the destination of a 'Store Finished Products' transfer to a sublocation within the warehouse caused the system to incorrectly break the MTO link. Now, the delivery order will always reserve the intended, freshly produced lot.
Original PR description
Steps to reproduce: - Create a storable product “P1” with Lot tracking - Enable routes: MTO + Manufacture - Create a BoM for the product: - Component: C1 - Configure the warehouse with 3-step…
Steps to reproduce:
- Create a storable product “P1” with Lot tracking
- Enable routes: MTO + Manufacture
- Create a BoM for the product:
- Component: C1
- Configure the warehouse with 3-step manufacturing
- Have on-hand stock in WH/Stock with Lot 001
- Confirm a Sales Order for the product
- Confirm the generated Manufacturing Order and produce Lot 002
- In the "Store Finished Products" transfer, change the destination location from WH/Stock to WH/Stock/Shelf 1 and validate
- Check the Delivery Order reservation
Problem:
The move is reserved with Lot 001 instead of 002
When using a 3-step manufacturing flow (MTO + Manufacture), if the user manually changes the destination of the "Store Finished Products" transfer to a sublocation of WH/Stock (e.g. WH/Stock/Shelf 1), the MTO link between the production and the delivery order was incorrectly broken, causing the delivery to reserve existing stock instead of the freshly produced lot.
Root cause: `_skip_push()` only skipped push logic when the downstream move's source was a child-or-equal of the current move's destination (`m.location_id._child_of(self.location_dest_id)`). When the destination was changed to a sublocation (WH/Stock/Shelf 1), this check failed, so `_push_apply()` ran, found the delivery's source (WH/Stock) was not a child of WH/Stock/Shelf 1, and called `_break_mto_link()`, clearing `move_orig_ids` on the delivery move. The delivery then fell back to make-to-stock reservation and picked an unrelated lot.
opw-6197212
Forward-Port-Of: odoo/odoo#268783This update resolves an issue where Peruvian tax reports couldn't generate closing entries due to a change in Odoo's accounting workflow. The fix creates a specific report variant for Peru, ensuring accurate tax calculations and restoring the automatic closing entry process for Peruvian businesses.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must precede the end time, improving usability for users creating shift templates. This ensures accurate shift scheduling.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
A recent test failed due to a minor issue with how content snippets were being dropped onto the website builder. This update corrects a positioning problem within the test environment, ensuring snippets are reliably placed in the intended location. This resolves a technical bug that didn't directly impact users.
Original PR description
Test that was testing that we cannot drop some snippets in a table of content sometimes failed due to the fact that it could sometimes drop in the wrong drop zone. This happens because 2 dropzones are really close to each other: <--- dropzone ---> [1] <--- toc start ---> <--- dropzone ---> [2] <--- section ---> <--- dropzone ---> [3] ... <--- toc end ---> When we move the snippet thumbnail to the dropzone [2], and drop it by calling `getDragHelper` it recomputes the position of the thumbnail, and sometimes it may drop the snippet in the first dropzone [1], breaking the test flow. We fix it by moving the snippet to the third dropzone [3], where it surely will drop, as there are no neighboring dropzones. runbot-241922 Forward-Port-Of: odoo/odoo#268473
This update clarifies the reporting of employee hours by renaming a confusing column from "Expected Hours" and "Theoretical Hours" to "regular hours". Previously, the column didn't accurately represent the employee's contracted work hours, leading to potential misinterpretations. This change ensures reporting aligns with the intended measure of actual work hours.
Original PR description
The column name "Expected Hours" and "Theoretical Hours" is confusing since it doesn't show the hours that the employee is supposed to work according to their contract, just the number of hours that are not considered overtime. This commit renames the column to better reflect the measure that is shown. task-6123642 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#262230
This update fixes a problem where receipt printing in Austria was incorrect, and prevented a deadlock during authentication with Fiskaly and FON. The changes ensure accurate receipt closing and a smoother authentication process for users in Austria, improving the overall POS experience.
Original PR description
In this task: -------------- - Fixed Austria closing receipt printing by calculating the offset from the last closed month instead of the current month. Closing records are returned in ascending order and exist only for completed months, so the latest month must use offset 0. - Prevent a deadlock during Fiskaly and FON authentication by checking for open sessions before starting any authentication flow, instead of after the first step of authentication. - The resp was used to show error which was not in the scope. task: 5420256 Forward-Port-Of: odoo/enterprise#119454 Forward-Port-Of: odoo/enterprise#102313
This update fixes a login issue in Safari's private browsing mode, where users were unable to complete the turnstile challenge. The fix addresses a conflict between Safari's tracking protection settings and Odoo's turnstile implementation, ensuring seamless login functionality.
Original PR description
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on…
Scenario: - set up turnstile - with recent safari mac os or ios (reproduced from 26.2) go to /web/login page in a private window - enter login and password and pass the turnstile challenge - click on Log in Result: nothing happens and there is an error in the console "An invalid form control with name='' is not focusable." Cause: By default Safari has the Settings > Advanced > "Use advanced tracking and fingerprinting protection" set to "in Private Browsing". If this options is enabled in private browser or in all browsing, you can't login to Odoo with turnstile because safari is preventing the update of the element that is preventing to send the form: <input style="display: none;" class="turnstile_captcha_valid" required> When turnstile challenge succeeds, a value should be set to this input that will unlock the form, the .value property is updated but the browser Shadow Content is not (and if we remove display:none, the input is empty). Fix: I've not been able to reproduce the issue without turnstile using same situation and iframe. We don't know Safari heuristic but the unlocking is working if: - we use setProperty instead of .value - we unset required - we remove the input - we display the turnstile_captcha_valid input before challenge This fix replaces setting .value by setProperty, and add a failsafe of unsetting required. opw-5917286 fixes #247536 Forward-Port-Of: odoo/odoo#253367
4 changes
Resolved issues and error corrections
This update fixes an issue where subscription product quantities weren't correctly applying pricelist rules, specifically when the quantity was set to 1. The change ensures that the unit price adjusts to the correct price based on the defined quantity tiers, improving the accuracy of subscription billing.
Original PR description
Steps to produce: --- - Install `sale_subscription` module. - Enable `pricelists` from Settings. - Create a new subscription product. - Create a new pricelist and Under Recurring Prices, add below…
Steps to produce:
---
- Install `sale_subscription` module.
- Enable `pricelists` from Settings.
- Create a new subscription product.
- Create a new pricelist and Under Recurring Prices, add below rules for
the monthly recurring plan on creatred subscription product:
- Min Qty = 0 then Price = 0.
- Min Qty = 10 then Price = 10.
- Min Qty = 20 then price = 20.
(This setup ensures the product is free when the quantity is less than 10, and
pricing increases based on the defined quantity tiers.)
- Create a sale order > Set a customer > Select the recurring plan as `Monthly` > Apply the created pricelist.
- Add the subscription product with quantity = 20 then Unit price is correctly set to 20.
- Change the quantity to 1.
Observation:
---
- The unit price does not update to 0 as expected.
Root cause:
---
- At [1], when quantity is updated to 1, `super()._get_pricelist_price()` correctly returns `0`.
- However, due to the `or self.price_unit` condition, the existing unit price is retained instead of applying the new value.
- This prevents valid pricelist rules (including zero-priced ones) from being applied.
Fix:
---
- As shown in [2], `line.pricelist_item_id` is set when a matching pricelist rule is found. Therefore, when a rule (including one for quantity = 0) applies, it will be reflected in `line.pricelist_item_id`.
- If `pricelist_item_id` is set, the computed price from the rule must be used; otherwise, fall back to the existing unit price.
[1]: https://github.com/odoo/enterprise/blob/7498010b8206df56fc5d8a9fd08b24169bf08cb2/sale_subscription/models/sale_order_line.py#L651-L654
[2]: https://github.com/odoo/odoo/blob/fab39bbea642c1a185e6cb91afea860fa0c0f27d/addons/sale/models/sale_order_line.py#L547-L557
opw-6122234
---This update significantly speeds up the process of adding and removing participants from marketing campaigns. The change optimizes a key function within the marketing automation module, reducing processing time from over 51 seconds to just 0.65 seconds when handling large campaigns (over 115,000 participants). This improves overall campaign management efficiency.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update resolves an issue where PE tax reports in Odoo 18.4 couldn't generate closing entries due to a change in the accounting workflow. The fix adds a dedicated Peruvian tax report variant and a Return Type, allowing users to correctly configure tax accounts and trigger the closing process safely, particularly in multi-VAT environments.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must be before the end time, improving clarity for users creating shift templates. This ensures accurate shift scheduling.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
2 changes
Resolved issues and error corrections
This update significantly improves the speed of syncing participants to marketing campaigns. By optimizing the underlying code, the process now takes just a fraction of the previous time – reducing it from over 51 seconds to less than a second. This change enhances the performance of our marketing automation tools, especially when managing large campaigns.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must precede the end time, ensuring correct shift template creation. This improves user experience and reduces confusion.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
7 changes
Resolved issues and error corrections
A recent update caused the Asset Depreciation Schedule report to crash when dealing with many assets grouped together. This fix ensures the report handles empty asset values correctly, preventing errors and allowing customers to generate reports without interruption. The change aligns with existing safeguards to ensure data integrity.
Original PR description
#### Description of the issue/feature this PR addresses: Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is…
#### Description of the issue/feature this PR addresses:
Opening the Asset Depreciation Schedule report with a period comparison enabled crashes with KeyError: 'no_format' when prefix grouping is active (large number of assets in one account group). The report becomes unusable for affected customers.
#### Current behavior before PR:
_regroup_lines_by_name_prefix sums each subline column by indexing prefix_subline['columns'][i]['no_format'] directly. Empty columns are built as {} by _build_column_dict (both col_value and col_data are None), so they have no 'no_format' key. With a comparison period enabled, an asset that has no value in the comparison period produces an empty column for that period; once prefix grouping fires (len(lines) >= prefix_groups_threshold, default 4000), the direct lookup hits that empty dict and raises KeyError: 'no_format'.
#### Desired behavior after PR is merged:
The prefix group total treats a missing 'no_format' as 0, matching the sibling caller in account_asset/models/account_assets_report.py that already guards with .get('no_format', 0). The report builds without crashing and the empty comparison column contributes 0 to the prefix group total.
opw-6225639
Forward-Port-Of: odoo/enterprise#119088This update fixes a bug where untaxed invoice lines in German accounting reports incorrectly inherited the Datev code from the previous line. This resulted in inaccurate Datev reports, which are crucial for compliance. The fix ensures untaxed lines have the correct, empty Datev code, improving report accuracy and reliability.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update resolves an error that occurred when confirming DHL deliveries. The system now automatically sets a future delivery date (one hour ahead) to avoid the 'date must be in the future' error, which previously prevented successful order confirmations. This ensures DHL delivery confirmations can always be processed correctly.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update resolves an error that occurred when creating payment reports for Swiss companies using the ‘l10n_ch_hr_payroll’ module. The issue stemmed from a missing module dependency, causing a value error during report generation. This fix ensures the payment report functionality works correctly for all company types.
Original PR description
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is…
*=l10n_ch_hr_payroll,hr_payroll_account_iso20022 When clicking the create payment report button on a payslip for a Swiss company, a traceback occurs if the ``hr_payroll_account_iso20022`` module is not installed. Steps to reproduce the error: - Install ``l10n_ch_hr_payroll`` module - Switch to CH Company - Create an Employee and running contract for it - Go to Payroll > Payslip > All payslips > Create a new payslip > Set the employee > Confirm > Create payment report Traceback: ```py ValueError: Wrong value for hr.payroll.payment.report.wizard.export_format: 'iso20022_ch' ``` https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip.py#L383 https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/l10n_ch_hr_payroll/models/hr_payslip_run.py#L13 Here, ``iso20022_ch`` is passed as ``export_format``, However, ``iso20022_ch`` is added to the selection field in the ``hr_payroll_account_iso20022`` module at [1]. When that module is not installed, the selection value does not exist, leading to the above error. [1]: https://github.com/odoo/enterprise/blob/7792926504a823590fbbe574a96994002a92fc17/hr_payroll_account_iso20022/wizard/hr_payroll_payment_report_wizard.py#L11 sentry-7391832811 Forward-Port-Of: odoo/enterprise#113277
This update significantly speeds up the process of adding and removing participants from marketing campaigns, particularly for large campaigns. The change optimizes how the system identifies and manages participants, reducing processing time from over 51 seconds to just 0.65 seconds. This improvement enhances campaign performance and user experience.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must be before the end time, ensuring correct shift template creation. This improves user experience and prevents confusion.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
A test failure in the SendCloud delivery module was resolved by adding default accounting data to the test environment. This prevents a database error related to missing tax information, ensuring test runs complete successfully. This fix addresses a runbot error and improves the stability of the delivery process.
Original PR description
Without demo data, test `test_sendcloud_delivery_with_downpayment` fails because of the absence of a default `account_tax` > psycopg2.errors.NotNullViolation: null value in column "tax_group_id" relation "account_tax" violates not-null constraint Fixes runbot errors 243069 - 243677 - 939245 Forward-Port-Of: odoo/enterprise#118639
9 changes
Resolved issues and error corrections
This update fixes a visual issue with the indeterminate checkbox in the Enterprise version of Odoo. The change ensures the checkbox's indicator is consistently visible across all environments, resolving a prior workaround. This improves the overall user experience and consistency.
Original PR description
The indeterminate checkbox is a [standard API](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:indeterminate#:~:text=true%3B%0A%7D-,Result,-Play) (JS and CSS only as @pparidans…
The indeterminate checkbox is a [standard API](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:indeterminate#:~:text=true%3B%0A%7D-,Result,-Play) (JS and CSS only as @pparidans noted), which has been implemented in Odoo in a couple of different ways, and is currently not working out-of-the-box (enterprise only): ------ PROBLEMS: - Original implementation was with JS because of a (now fixed) owl issue: see [ web/static/src/search/search_panel/search_panel.xml](https://github.com/odoo/odoo/blob/c0c82927f2e7e2a54749a0e081d8a03b9ef654e2/addons/web/static/src/search/search_panel/search_panel.xml#L99-L103) & https://github.com/odoo/owl/issues/713 - The new intended odoo-api for the indeterminate checkbox (`t-att-indeterminate` or `<Checkbox indeterminate="...")` doesn't work with enterprise installed because: `web_enterprise/static/src/scss/bootstrap_overridden.scss` sets `$component-active-color: unset !default;` & Bootstrap's uses `$form-check-input-indeterminate-color: $component-active-color` therefore resolves to `unset`, making the dash invisible. -> This was fixed in studio only (odoo/enterprise#81372) but should apply globally. ------ FIXES: - Refactor the JS workaround to use the `t-att-indeterminate`, simplifying the code in `web` (with the help of owl magic) - Apply the studio fix globally to enterprise module (we keep the studio fix with custom svg because the color pattern of studio is a bit different, so removing the custom svg makes the UI look less good). Community PR: https://github.com/odoo/odoo/pull/268491
This update ensures that the phone numbers dialed through the Odoo Enterprise system now use the sanitized E164 format, rather than the raw, user-entered number. This change improves accuracy and reliability when making calls or sending messages, aligning with updated phone widget functionality.
Original PR description
This commit ensures that the sanitized phone number is the one passed to the softphone + displayed instead of the raw phone number. Task-5184717 Community: https://github.com/odoo/odoo/pull/261001
This update fixes an issue where the manual prorata year selection for Belgian VAT returns wasn't being saved correctly. Previously, the system defaulted to the current year regardless of user input. The fix ensures that the user's chosen prorata year is accurately reflected in the generated VAT XML, improving data accuracy and compliance.
Original PR description
### Issue before this commit: Manually modifying the "Prorata Year" in the Belgian VAT return lock wizard was ignored. The generated XML always exported the tax return's current year instead of the user's input. ### Steps to reproduce the issue: 1. Download Accounting and l10n_be 2. Switch to BE company 3. Open a tax return for 7 April (as an example) 4. Try to validate the VAT March 2026 ### Cause of the issue: The prorata_year field was a computed field lacking the store=True attribute. Upon validation, the unsaved manual input was lost, triggering the compute method which blindly overwrote it with the default year. https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/l10n_be_reports/wizard/vat_return_lock_wizard.py#L18 ### Reason to introduce the fix: Adding store=True ensures the user's manual override is persisted in the database and correctly injected into the Intervat XML payload. opw-6165520
This update consolidates three separate rules related to unpaid leave into a single, more efficient process. This change creates a central source of truth for calculating unpaid days, improving accuracy and reducing complexity in payroll processing. The update also includes a related test to ensure the new rule functions correctly.
Original PR description
Purpose: As of now, we have 3 seperate rules and all of them deal with the same deductable items which is (Unpaid leave). so instead of doing that, we need to have one source of truth for unpaid days. Current behavior: - dropped the out of contract salary rule - removed the fully unpaid sick leaves from sick leave deduction rule - grouped unapid leaves, unpaid sick leaves and out of contract days under one rule - reintroduced deleted test task-id: 6229123
This update strengthens the validation process for recruitment integration settings. Specifically, a required label has been added to the integration_state_selection field, ensuring data integrity and preventing errors. This improves the reliability of the recruitment process by enforcing correct configuration.
Original PR description
This commit adds a label to the option of the field integration_state_selection. The label is a mandatory property and an error is thrown if it is not given.
This update fixes an issue where the activity rate used in Swiss payroll calculations was incorrectly tied to individual employees. Now, the rate is based on the Odoo Enterprise version, ensuring accurate and compliant payroll processing for Swiss businesses. This change improves the reliability of financial reporting and payroll accuracy.
Original PR description
…ployee Forward-Port-Of: odoo/enterprise#119658
This update streamlines the payment refresh button in the Odoo Enterprise system. Previously, the button was always visible, leading to unnecessary system calls. Now, it only appears for payments that are actively being processed (pending or unsigned), optimizing performance and reducing strain on the system.
Original PR description
… batches The refresh button was always shown, which could cause unnecessary calls to OdooFin if the payment is finalised (accepted, rejected or canceled). With this change, the button is shown only for payments in progress (pending or unsigned). task-6103900 Forward-Port-Of: odoo/enterprise#113182
This update fixes an issue where flexible schedules were incorrectly calculating work hours, leading to inaccurate payroll totals. The change decouples the hour splitting logic, now relying on specified daily hours instead of attendance hours, ensuring accurate half-day and full-day calculations.
Original PR description
Steps: - Create half day off for an employee - Create a full day off of the same type - Create a payslip for the employee Issue: - Due to the lack of attendance hours in the flexible schedules, the _get_work_hours_split_half is unable to split half day and full days work entries of the same type. - Half worked days will be rounded up which affects the total number of work days in a month Solution: The approach was to decouple the work_hours_split_half functionality from the attendance hours and rely on the specified hours_per_day instead. This accurately splits half and full days. Task: 6253675 Forward-Port-Of: odoo/enterprise#118968 Forward-Port-Of: odoo/enterprise#118836
This update refines the calculation of worked days for payroll, addressing inconsistencies and improving accuracy. The changes enhance the reliability of payslip generation, ensuring employees are paid correctly based on their actual working hours. This update impacts the core payroll functionality.
17 changes
Resolved issues and error corrections
This update fixes an issue where the VAT reports for Spanish companies were incorrectly including withholding taxes in the total VAT calculation. The fix excludes 'retencion' (withholding tax) from the VAT calculation, ensuring accurate VAT reporting figures. This improves the reliability of financial reports.
Original PR description
Step to reproduce - install `l10n_es_reports` and switch to ES company - create a invoice, add a product, set price = 100 - add two taxes (one should be withholding tax) ex: 21%G and 19%whi - confirm it, total payable is now 100 + 21 - 19 = 102 - open vat Books report for ES, see line for this invoice Observation: - for this invoice, in total vat column, we get 102 value - it should be 100+ 21 i.e 121 as we do not include withholding taxes in total vat Cause: - the query for report used to sum up all the taxes for calculating vat Fix: - excluded tax of type "retencion" in tax summation opw-6082329
This update resolves an issue where generating the general ledger report could create extremely large PDF files due to lengthy invoice references. By limiting the length of invoice references, we prevent the PDF from becoming bloated and ensure reports generate reliably, avoiding system errors related to file descriptor limits.
Original PR description
The display name of the account.report.line in the general ledger report has the format of: INVOICE NAME (invoice refs) In the case where a client has hundreds of sales orders batched to a single…
The display name of the account.report.line in the general ledger report has the format of: INVOICE NAME (invoice refs) In the case where a client has hundreds of sales orders batched to a single invoice, the ref can become extremely long, e.g.: INV/2026/00001 (S12123, S12152, S12159, S12140, S12165, S12161, S12162, S12110, S12099, S12124, S12145, S12128, S12114, S12131, S12097, S12185, S12154, S12133, S12190, S12118, S12116, S12102, S12155, S12153, S12158, S12150, S12100, S12142, S12121, S12122, S12111, S12187, S12172, S12177, S12095, S12117, S12144, S12137, S12092, S12138, S12186, S12182, S12112, S12148, S12183, S12101, S12178, S12119, S12169, S12115, S12146, S12093, S12126, S12160, S12163, S12129, S12098, S12151, S12096, S12174, S12120, S12130, S12147, S12180, S12191, S12164, S12141, S12105, S12136, S12139, S12109, S12106, S12104, S12103, S12175, S12179, S12188, S12113, S12173, S12167, S12171, S12134, S12094, S12184, S12166, S12170, S12125, S12135, S12143, S12176, S12189, S12156, S12181, S12107, S12157, S12132, S12149, S12127, S12108, S12168...) Because the length of the account.report.line is unchecked in account_general_ledger.py label builder, the pdf can clog to one or two account.report.lines per page, skyrocketing the pdf page length. As wkhtmltopdf processes the report from html to pdf it makes a system call openat() to the /tmp/report.footer.tmp.x.html file for EACH page of the pdf. You can see the TODO comment in the spoolTo function in wkhtmltopdf (both in Odoo and the original repo) saying that the header and footer need to be freed, on each page processing, not just null pointed. https://github.com/odoo/wkhtmltopdf/blob/2c884bd1545b8a639847de22f24754ee5a6fc44c/src/lib/pdfconverter.cc#L794 I verified that that the number of openat calls to the /tmp/report.footer.tmp.x.html file equals the exact number of pages in the pdf to be generated if the report HAD generated successfully by setting the footer input into _run_wkhtmltopdf to None, generating the report without footers, then separately running an strace on wkhtmltopdf when the report fails to generate. See related ticket linked at bottom. The linux machine used on sh instances has a ulimit -n of 1024 file descriptors. Because the footer file descriptors accumulate, once a pdf has about 1010+ pages (~a dozen fd's are allocated for other purposes), over 1024 file descriptors are opened and the system fails with: Wkhtmltopdf failed (error code: -6). Message: QEventDispatcherUNIXPrivate(): Unable to create thread pipe: Too many open files QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe Since wkhtmltopdf is archived and Odoo has a replacement in development, I suggest that we limit the display_name of the account.report.line to 200 to keep the bloat minimized, preventing one account.report.line's name from taking up an entire page of the general ledger pdf. This allows many more batched invoices to be shown in the report and a much greater time range of data to be printed without hitting the fd limit. I suggest changing it at the general ledger report level rather than in the account.move.line _compute_display_name function, as we probably still want to see the full display_names at the invoice level. On runbot, the machine has different memory constraints than on sh / local, so it hits the following error before the one above: Wkhtmltopdf failed (error code: -11). Memory limit too low or maximum file number of subprocess reached. Message : Steps to Reproduce on 19.0 newdb: 1. newdb -n test_gl -v 19.0 2. ensure ulimit is set to 1024 in shell that runs odoo instance by running ulimit -n 1024 to mimic ulimit of sh environment 3. run db with python3 odoo-bin, ensuring high enough memory constraints to simulate multi worker sh instance, i.e. --limit-memory-soft=12884901888 --limit-memory-hard=1288490188 4. install sales, accounting, stock 5. install demo data 6. create invoices with 100+ associated sales orders 7. generate the pdf 8. Increase the amount of invoices till the general ledger page count hits ~1010+, where you will hit the error. Notes: opw-ticket-6201508 closes #118067
This update corrects a reporting issue where tax reports for Moroccan companies were incorrectly including entries with zero balances. The fix filters out these zero-balance lines, ensuring the reports accurately reflect financial data. This improves the reliability of tax reporting for our Moroccan clients.
Original PR description
When generating the tax report for a Moroccan company, entries with a zero balance were appearing in the report. Steps to reproduce: ------------------- * Create a Moroccan company * Create a bill with a tax to pay * Change the bill date and accounting date to a past date * Make a first payment of the bill, with a date to today * Unreconcile the payment, and make a second payment with a date in the past (the same one as the bill date for example) * Now generate the tax report for the period of today > Observation: The report contains useless entries with a zero balance. Why the fix: ------------ We add `HAVING SUM(account_move_line.balance) != 0` to filter out the line that have a zero balance. opw-5911669
This update addresses a performance issue within the Dimona payroll module for Belgium. By adding missing indexes to key database tables, the system now processes payroll calculations more efficiently, reducing potential delays and improving overall responsiveness. This enhancement ensures smoother and faster payroll processing for our Belgian clients.
Original PR description
opw-6241383 runbot-233176
This update resolves an issue where inventory counts weren't accurately recording products without lot numbers. The fix ensures that new units without lots are correctly added to inventory counts, preventing miscounts and improving data accuracy. It addresses a validation error related to how the system handles lotless products during inventory adjustments.
Original PR description
### Steps to reproduce: 1. Create a product tracked by lot 2. Put 10 units in WH/Stock without lot 3. Inventory > Operations > Adjustments > Physical Inventory 4. Select the line referring to your…
### Steps to reproduce: 1. Create a product tracked by lot 2. Put 10 units in WH/Stock without lot 3. Inventory > Operations > Adjustments > Physical Inventory 4. Select the line referring to your product and request an inventory count + Show Expected Quantity 5. Open the barcode app > Count Inventory 6. Scan your product #### > The line is not selected, in particular, next scans will be re-interpreted as product scans rather than new serial creation for your product. ### Cause of the issue: Scanning your product search a line to select if any: https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/stock_barcode/static/src/models/barcode_model.js#L1432-L1435 https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/stock_barcode/static/src/models/barcode_model.js#L1630-L1632 However, the `findLine` will fail since this method calls the `_canOverrideTrackingNumber` to determine if the lot of the barcodData matches the one of the line: https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/stock_barcode/static/src/models/barcode_model.js#L1859-L1863 But, the override of the `_canOverrideTrackingNumber` method for the `BarcodeQuantModel` does not handle the absence of lotName in the barcodeData correctly as it does not consider that a line without lot can be overridden by an empty lotName: https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/stock_barcode/static/src/models/barcode_quant_model.js#L729-L731 Note however that the super call does: https://github.com/odoo/enterprise/blob/bce04ce24b66fb1a2481274eb3aebdc30a62766e/stock_barcode/static/src/models/barcode_model.js#L795-L798 ### Issue 2: ### Steps to reproduce: - Steps 1 -> 5 - Click on your product line to select it - Scan a new lot to add one new unit referring to that lot - Confirm (1) - Apply Now #### > User Error: Quant's editing is restricted, you can't do this operation Since the line is selected, you have a currentLine during the `processBarcode` and hence the existing line will be updated using the `lotName``: https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/stock_barcode/static/src/models/barcode_model.js#L1560-L1584 However, writing on the line will then try to write on the related quant during the validation process which will be forbiden since we are not allowed to change the lot of an existing quant: https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/addons/stock/models/stock_quant.py#L351-L360 Now, the issue is that actually due to the nature of the line and of the barcode data, the line lot is not expected to be updated but rather a new line is expected to be created: https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/stock_barcode/static/src/models/barcode_model.js#L795-L798 Additional issue: Fixing issue 1 and 2 highlight and other issue of the validation process: - Steps 1 -> 6 > The line gets selected - Scan a newlot > a new subline is added referring to 1 unit of your new quant - Confirm (1) > Some serials where not counted, set them as missing #### > Check your quants: the 10 unit lotless quant was not updated but a new quant for 1 units was created for your newlot ### Cause of the issue: Applying all quantities is expecting to toggle them as counted before applying to update the existing quants: https://github.com/odoo/enterprise/blob/c8535a7a0e2eae811048a34a0bae187a1fa45311/stock_barcode/static/src/models/barcode_quant_model.js#L72-L82 https://github.com/odoo/enterprise/blob/c8535a7a0e2eae811048a34a0bae187a1fa45311/stock_barcode/static/src/models/barcode_quant_model.js#L287-L296 However, only line tracked by serial numbers are set as counted: https://github.com/odoo/enterprise/blob/c8535a7a0e2eae811048a34a0bae187a1fa45311/stock_barcode/static/src/models/barcode_quant_model.js#L60-L63 opw-6212923
This update corrects a bug in the accrual reports (like 'Bill To Receive') that caused group totals for 'Received,' 'Billed,' and 'Amount' to incorrectly show as zero. The fix ensures these reports accurately reflect aggregated data, which is essential for accountants during financial closing processes. This improves the reliability of key financial reporting.
Original PR description
### Issue before this commit: In accrual reports (e.g., "Bill To Receive", "Billed Not Received", "Invoices To Be Issued", and "Invoices Not Delivered"), when grouping the list view by fields such as…
### Issue before this commit: In accrual reports (e.g., "Bill To Receive", "Billed Not Received", "Invoices To Be Issued", and "Invoices Not Delivered"), when grouping the list view by fields such as Vendor, the group header totals for the "Received", "Billed", and "Amount" columns display 0.00 even if the interanl lines of the group are not 0.00. ### Steps to reproduce the issue: 1. Download Purchase Accounting and Sale Accounting 2. Go to one of this pages: Billed Not Received, Bill To Receive, Invoices To Be Issued, and Invoices Not Delivered 3. Ensure the view is in its default grouping (grouped by Vendor or Customer) 4. Observe the group header rows for the Received (or Delivered), Billed (or Invoiced), and Amount columns. They all display 0.00 5. Expand a group that contains records with values greater than zero 6. Observe that the individual records populate correctly, but the aggregated group header row continues to display 0.00. ### Cause of the issue: The commit ddc1b681656ea8c70f3231cda20b5a58b9ff7dd6 adapted the code to retrieve the new accrual reports but attempted to fetch grouped records using group[0].id as the dictionary key, while the grouped() method actually used the recordset object as the key. This mismatch caused the dictionary lookup to fail, resulting in 0.00 sums. https://github.com/odoo/enterprise/blob/c8535a7a0e2eae811048a34a0bae187a1fa45311/account_accountant/models/analytic_mixin.py#L40-L48 ### Reason to introduce the fix: This fix restores the core analytical utility of the accrual reports, which are crucial for accountants during period-end closings to evaluate totals at a glance. opw-6232273
This update fixes an issue where adding a recurring product to a confirmed sales order without a linked subscription plan would cause an error. The change prevents this by validating the product type and displaying a user-friendly error message, ensuring correct recurring product setup.
Original PR description
Steps to reproduce: - Go to Sales → Products. - Create a Service product and enable the Recurring option. - Open an already confirmed Sales Order that does not contain any recurring products. - Add the newly created recurring product to the confirmed order. - Click Save. - Observe that a traceback occurs. Cause: - When adding a recurring product without a subscription plan to a confirmed Sale Order, _timesheet_create_task() attempts to compute a start date using order.next_invoice_date, which is not set. - This leads to a TypeError when `order.next_invoice_date` receives `False`. Solution: - Add a validation to prevent adding recurring products without a subscription plan and raise a proper `UserError` instead of allowing the code to reach task generation logic. task-5932700 Forward-Port-Of: odoo/enterprise#119942 Forward-Port-Of: odoo/enterprise#107691
This update fixes a bug where untaxed invoice lines in German reports incorrectly inherited the Datev code from the previous line. The fix ensures that untaxed lines now properly display an empty Datev code, aligning with German tax regulations. This prevents reporting discrepancies and ensures accurate financial data for Datev.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update ensures that undoing the auto-plan feature correctly preserves the initial workload assigned to a shift. Previously, the system recomputed the workload, leading to inaccurate shift allocations. This fix maintains the intended functionality of the auto-plan process.
Original PR description
Steps to Reproduce --- 1. Open the Planning module 2. Create an open shift with allocated_hours 3. Click Auto Plan 4. Click Undo on the auto-plan notification Issue --- Undoing an auto-plan operation…
Steps to Reproduce --- 1. Open the Planning module 2. Create an open shift with allocated_hours 3. Click Auto Plan 4. Click Undo on the auto-plan notification Issue --- Undoing an auto-plan operation triggers recomputation of allocated_hours, causing the shift to lose its original workload value. Current Behaviour --- When resource_id is set to False during undo: - _compute_allocated_hours is triggered (depends on resource_id) - _compute_allocated_percentage is triggered (depends on allocated_hours) - Both fields are recalculated, potentially changing allocated_hours from its pre-assignment value Expected Behaviour --- Undoing auto-plan should preserve allocated_hours at its pre-assignment value while allowing allocated_percentage to adapt to the new context (open slot vs assigned resource). Fix --- Use protecting context manager in action_rollback_auto_plan_ids to prevent allocated_hours from being recomputed when resource_id is removed. This allows allocated_percentage to recalculate naturally based on slot duration while keeping allocated_hours stable. task - 4952149 Forward-Port-Of: odoo/enterprise#119772 Forward-Port-Of: odoo/enterprise#102864
This update resolves an error that occurred when confirming DHL deliveries. The system now automatically sets a future delivery date (one hour ahead) to avoid the 'date must be in the future' error, which previously prevented successful order confirmations. This ensures DHL delivery confirmations can always be processed.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update resolves an issue in the Data Cleaning app where record IDs were incorrectly summed and displayed alongside group names, causing truncation and misrepresentation of data. The fix removes the default 'sum' aggregator for integer fields, ensuring group headers accurately show the count of records.
Original PR description
## Issue In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="709" height="374" alt="6166623-before" src="https://github.com/user-attachments/assets/9d80b1ec-49c0-4b7f-8c6e-53846f9e433e" />
## Steps to reproduce
1. Install *Data Cleaning* (`data_cleaning`)
2. In Data Cleaning > Configuration > Field Cleaning, create a new rule (or edit an existing one):
- Any name
- Model: *Contact*
- Rule:
- Field to Clean: *Name (Contact)*
- Action: *Set Type Case* - Case: *All Uppercase*
4. Click the *Clean* button in the upper left corner
5. In Data Cleaning > Field Cleaning, group the records by any field (e.g., *Field*)
6. **The name of the group (_Name (Contact)_) is truncated, making it and the record count unreadable. This is due to the sum of _Record ID_ being displayed in the same row, even though that information is irrelevant.**
## Cause
The *Record ID* (`res_id`) field is an Integer field defined [here](https://github.com/odoo/enterprise/blob/3603afdd5c0d19c9276f3855156be4040ab5717d/data_cleaning/models/data_cleaning_record.py#L20). By default, Integer fields have the `sum` aggregator:
https://github.com/odoo/odoo/blob/681610c002a310f1c73fc2e5bec8d3dae27bc4a7/odoo/orm/fields_numeric.py#L17-L23
This causes the IDs to be summed up and appear in the group headers.
## After
<img width="740" height="370" alt="6166623-after" src="https://github.com/user-attachments/assets/a42d8f58-06dc-4308-8b6f-1ab09e8034f8" />
related: https://github.com/odoo/odoo/pull/265163
opw-6166623This update significantly speeds up the process of adding and removing participants from marketing campaigns. By optimizing a key database function, the system now completes this task in just a fraction of the time – reducing it from over 51 seconds to less than a second. This improvement will result in quicker campaign updates and a smoother user experience.
Original PR description
Replace search_read with search_fetch to avoid unnecessary _read_format call in backend context. Use OrderedSet instead of a custom _uniquify_list helper to get O(1) membership tests when computing records to add or remove from campaigns. Benchmark on a campaign with 115k participants: | Before PR | After PR | |:---------:|:--------:| | 51.71s | 0.652s | opw-6055334 Forward-Port-Of: odoo/enterprise#119589 Forward-Port-Of: odoo/enterprise#117656
This update resolves an issue where Peruvian tax reports couldn't generate closing entries after the 18.3 update. The fix creates a specific tax report variant for Peru, ensuring accurate VAT calculations and restoring the automated closing entry process for Peruvian businesses. This prevents errors and allows for proper tax account configuration.
Original PR description
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that…
### Issue Since the introduction of the Tax Returns feature in 18.3, it was no longer possible to generate a Closing Entry as the button has been replaced by Returns The Return mechanism implies that you need a Return Type in order to make a Closing Entry using the Validate button Additionally, using the Generic Tax Report by default creates a risk in Multi-VAT environments, as it mixes taxes from all countries instead of isolating Peruvian taxes ### Cause The new 18.3 accounting workflow requires at least one active Return Type associated with a country-specific report variant to display the Return options and process the closing entry Peru was relying on the Generic Tax Report, without a dedicated report variant No Return Type was configured, which blocked Odoo's automatic VAT closing workflow and prevented the system from prompting the user to configure the required closing accounts ### Steps to reproduce - Install `l10n_pe_reports` and `accountant` - Switch to a PE Company - Go to the Tax Report Before the fix, no Returns button is available for any of the existing reports, making it impossible to use Odoo's automatic process to configure the tax accounts and trigger the closing entry ### Notes This is fixed by creating a dedicated Peruvian tax report variant directly in Enterprise that inherits from the generic tax report A custom handler is added to force the domain filtering on Peruvian taxes only, and a corresponding Return Type is defined to restore the full closing entry process safely opw-5978673 Forward-Port-Of: odoo/enterprise#117891
This update fixes a misleading error message displayed when a shift template's start time was set after its end time. The message has been corrected to accurately state that the start time must be before the end time, ensuring correct shift template creation.
Original PR description
Before this commit, when the user set a start hour after end hour, the error message raised said: "The start hour cannot be before the end hour for a one-day shift template.". Which does not make sense since the start hour has to be before the end hour to be valid. This commit fixes the error message to say the start hour cannot be after the end hour. Forward-Port-Of: odoo/enterprise#119637
This update resolves an issue where the barcode inventory count feature would fail when using archived units of measure. The fix ensures that archived UoMs are correctly included in the inventory count cache, allowing accurate counts to be performed. This prevents errors during physical inventory adjustments.
Original PR description
### Steps to reproduce: - In the settings enable: "Units of Measure & Packagings", "Storage Locations" - Create a product in units and register 1 unit in stock - Inventory > Operations > Adjustments…
### Steps to reproduce: - In the settings enable: "Units of Measure & Packagings", "Storage Locations" - Create a product in units and register 1 unit in stock - Inventory > Operations > Adjustments > Physical Inventory - Select your line and request a count > Set Current Value - Inventory > Configurations > units of measures > UOM categories - Select unit and archive it - Go to the barcode app > Click Count inventory ### > Owl error: Uncaught promise ### Cause of the issue: Since the uom used on the quant is archived, it is not found by the search used to fill the barcodeCache: https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/components/main.js#L209-L213 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/models/stock_quant.py#L104-L106 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/components/main.js#L229 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/models/barcode_model.js#L37-L39 However, if the uom is not present in the barcode cache the `BarcodeQautnModel` will fail to createLinesState whihc raises a missing error: https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/models/barcode_quant_model.js#L712 https://github.com/odoo/enterprise/blob/26546bcd3beebc7f65ce08385441b6284b46598e/stock_barcode/static/src/lazy_barcode_cache.js#L107-L110 opw-6250090 Forward-Port-Of: odoo/enterprise#118987 Forward-Port-Of: odoo/enterprise#118813
This update resolves a potential error in the Hong Kong payroll calculations. Specifically, it now checks for a missing resource calendar or zero hours per week, preventing a division-by-zero issue that could have disrupted payroll processing. This ensures accurate and reliable payroll calculations for Hong Kong businesses.
Original PR description
. Add a check for a null resource calendar and zero hours per week. task-6229271 Forward-Port-Of: odoo/enterprise#117685
This update fixes an issue where barcode scanning incorrectly displayed delivered quantities on sales orders. The problem stemmed from how the system selected lines during delivery updates, leading to inaccurate order fulfillment. The fix ensures correct quantity updates when using barcode scanning with lots.
Original PR description
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities. ## Steps to replicate: - Install Sales and Barcode (no demo data). - Enable Lots & Serial…
Currently when user adds adds quantity in barcode using lots it leads to incorrect sale order quantities.
## Steps to replicate:
- Install Sales and Barcode (no demo data).
- Enable Lots & Serial Numbers in settings.
- Create Test Product with Tracking by Lots.
- Go to Inventory > Products>Lots & Serial Numbers and create 3 lots for the product.
- Update each lot’s on-hand quantity to 10 from the product page.
- Create and confirm a Sales Order for the product (lines: qty 3 and 2 units).
- Open the delivery in the Barcode app:
- Scan lot 2 > increase qty to 3 using +1 button
- Scan lot 3 > increase qty to 2 using +1 button
- Validate and go to the sale order.
## Observed Behavior:
The sale order delivered quantities are flipped and a backorder is created even though the quantity for the product is satisfied.
## Root cause:
The issue occurs because when a sales order is confirmed, the system defaults to
using lot 1 on the delivery receipt. When a user scans lot 2, the `_processBarcode` function is triggered, which calls `_findLine` at [1] to select the appropriate line on the receipt.
As the loop in `_findLine` iterates through `pageLines` with values like:
```
[{display_name: "Test product", quantity: 3, lot_id: { name: 'lot1' }},
{display_name: "Test product", quantity: 2, lot_id: { name: 'lot1' }}]
```
During the first iteration, `foundLine` is set at [2] for the line with quantity 3 . Since the subsequent if condition is not satisfied, the loop hits the continue block at [3].
On the next iteration, the line with quantity 2 causes `foundLine` to be overwritten at [2], and the continue block is executed again at [3].
This results in the line with quantity 2 being selected as the line to update at the end of the function.
When the user manually increases the quantity to 3, the line that originally required quantity 2 is updated and fulfilled.
Later, when lot 3 is scanned, the line that required quantity 3 is selected for update, and manually increasing the quantity to 2 before validating the order leads to a backorder and causes the delivered quantities to be flipped.
[1]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1335-L1337 [2]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1690-L1699 [3]:
https://github.com/odoo/enterprise/blob/81eaeb4b18d849c644160234def6c69013591abe/stock_barcode/static/src/models/barcode_model.js#L1727-L1729
## Solution:
Avoid grouping lines from different moves unless using batch transfers. This ensures that backorders are not created when the barcode lines are fulfilled.
opw-5423943
Forward-Port-Of: odoo/enterprise#118085
Forward-Port-Of: odoo/enterprise#1090328 changes
Resolved issues and error corrections
This update resolves an issue where SEPA QR codes were occasionally displaying incorrect decimal places due to floating-point calculations in the system. The change ensures the QR code amount accurately reflects the currency's precision, preventing potential payment errors. This improves the reliability of vendor bill payments generated via QR code.
Original PR description
**Description of the issue/feature this PR addresses:** When generating a SEPA QR code for a vendor bill payment, the embedded amount could occasionally contain excess decimal places instead of…
**Description of the issue/feature this PR addresses:** When generating a SEPA QR code for a vendor bill payment, the embedded amount could occasionally contain excess decimal places instead of respecting the currency's expected precision. This occurs because the `amount` variable in `_get_qr_vals` was being converted directly using `str(amount)`. Due to Python's floating-point arithmetic, the float value in memory can contain decimal drift. Directly casting it to a string exposes this drift in the payload. This commit resolves the issue by replacing `str(amount)` with `float_repr(amount, currency.decimal_places)`. This safely bypasses the float representation issue, ensuring the string strictly respects the currency's configured decimal precision before being injected into the QR code. opw-5504258 **Steps to reproduce:** - Select company “My Belgian Company” - Create a 23% purchase tax - Create vendor bill - Select Vendor “BE Company CoA” - Choose any single product, change price to 37.18 and choose the 23% tax. The Untaxed Amount should be 37.18, VAT tax should be 8.55, and Total should be 45.73 - Confirm > Register Payment > scan QR code. EUR45.730000000000004 should show **Current behavior before PR:** - When generating a SEPA QR code for a payment, the embedded amount can contain excess decimal places due to floating-point drift. **Desired behavior after PR is merged:** - The SEPA QR code is generated with the correct number of decimal places. Forward-Port-Of: odoo/odoo#267293
This update fixes a bug where untaxed invoice lines were incorrectly inheriting the Datev code from the previous line, leading to inaccurate reports. The change ensures that untaxed lines now correctly have an empty Datev code, resolving a reporting discrepancy. This improves the accuracy of financial reports generated for German businesses using the Datev system.
Original PR description
**PROBLEM** Untaxed move lines would take the datev code of the previous line instead of having no datev code like they should. **STEP TO REPRODUCE** 1. On a german company, create an invoice with a line with tax 19% I, and a line that is untaxed (with a non-null price). 2. On the general ledger, generate the datev zip. 3. Unzip, and open the account entries csv, and notice the 2nd line of the invoice as the datev code set to something instead of it being empty (column BU-Schlüssel). opw-6141003 Forward-Port-Of: odoo/enterprise#118486
This update resolves a problem where DHL delivery confirmations were failing due to incorrect scheduled dates (past dates). The system now automatically sets a future date (one hour ahead) to ensure successful confirmation, preventing delivery errors and improving order processing.
Original PR description
When confirming the delivery of an order using DHL shipping method we get an error that the date must be in the future. This happens when the scheduled date was not set, or set for a time in the past. This commit automatically sets the time to 1 hour in the future and bypasses the user error. opw-6148927 Forward-Port-Of: odoo/enterprise#116211
This update resolves a rounding issue that occurred when generating PEPPOL invoices, specifically impacting unit prices. The change reverts a previous update that introduced this problem, ensuring accurate pricing calculations for international transactions. This improves the reliability of invoices for our business partners using PEPPOL.
Original PR description
Reverts https://github.com/odoo/odoo/pull/262242 opw-6293201
This update resolves a problem where the PDF Quote Builder generated incorrect data due to how it handled temporary records during the demo setup. The fix ensures that all data changes are immediately applied within the transaction, preventing inconsistencies and errors when the builder is enabled. This ensures the PDF quote builder functions correctly after demo data is used.
Original PR description
Steps to produce: --- - Install sale_management and website_sale modules with demo data. - From settings, disable the PDF Quote Builder. - Go to Settings > Technical > Sequences & Identifiers >…
Steps to produce:
---
- Install sale_management and website_sale modules with demo data.
- From settings, disable the PDF Quote Builder.
- Go to Settings > Technical > Sequences & Identifiers > External Identifiers.
- Delete the `consu_delivery_02_product_template` identifier.
- From settings, try to enable the PDF Quote Builder again.
Issue:
---
```py
insert or update on table "quotation_document_sale_pdf_form_field_rel" violates foreign key constraint
"quotation_document_sale_pdf_form_fie_quotation_document_id_fkey"
DETAIL: Key (quotation_document_id)=(1) is not present in table "quotation_document".
```
Cause:
---
When the XML demo loader processes **`sale_pdf_quote_builder_demo.xml`**, it calls `create()` on `quotation.document` for each of the 5 demo records one by one. Each create() call receives vals_list that contains datas, the actual PDF base64 content.
Inside `super().create(vals_list) `[1], the ORM writes datas to `ir_attachment`. Since `form_field_ids` is a `store=True` computed field with `@api.depends('datas')` [2], the ORM knows it needs to recompute `form_field_ids`. But it does not run the computation immediately. It simply registers the records in a pending recompute set and moves on. Nothing hits the DB yet for this compute.
After `super().create() `returns, the `write({'res_model': ..., 'res_id': ...})` runs. Since `res_model` and `res_id` live on `ir_attachment` (the parent table via _inherits), this write is also not immediately flushed to the DB. The ORM marks it as dirty in the cache and defers it.
So after all 5 records are created, the ORM holds two deferred things: a dirty UPDATE ir_attachment write for all 5 records, and a pending recompute for `form_field_ids` on all 5 records. Nothing has been flushed to the DB yet.
When the demo XML tries to reference `product.consu_delivery_02_product_template` [3], which no longer exists,
a ValueError is raised. From `load_demo()` [4], the savepoint is rolled back.
After the except block logs the failure, execution continues in l`oad_module_graph()` which calls `env.cr.commit()`. This triggers f`lush() -> transaction.flush() -> flush_all() -> _recompute_all()`. The ORM processes the pending recompute registry and finds `form_field_ids` needs recomputing for quotation.document(1, 2, 3, 4, 5). It calls `_compute_form_field_ids`() on those stale ids. Inside that compute, `_create_or_update_form_fields_on_pdf_records()` tries to insert into `quotation_document_sale_pdf_form_field_rel` with quotation_document_id=1. But quotation_document id 1 no longer exists in the DB — it was rolled back — so PostgreSQL raises the foreign key violation.
This is confirmed by the traceback from `_compute_form_field_ids`, which shows the call chain going through `commit() -> flush_all() -> _recompute_all()` rather than through `create()`, proving the compute fired after the rollback using stale ORM cache state.
Fix:
---
Calling `docs.flush_recordset()` at the end of `create()` forces all pending writes and pending recomputes to be executed immediately, while still inside the savepoint scope:
- It flushes the dirty res_model/res_id write on the ir_attachment parent table, so UPDATE ir_attachment hits the DB inside the savepoint.
- It triggers `_recompute_all()` for the pending `form_field_ids` compute on docs, so `_compute_form_field_ids()` runs inside the savepoint and the INSERT into `quotation_document_sale_pdf_form_field_rel` happens while the quotation_document rows still exist in the DB.
If the savepoint then rolls back, the ORM cache has nothing dirty or pending left. The subsequent commit() in `load_module_graph()` finds nothing to flush, so no stale writes execute against non-existent ids and no foreign key violation occurs.
[1]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/models/quotation_document.py#L93-L98
[2]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/models/quotation_document.py#L62-L71
[3]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/addons/sale_pdf_quote_builder/data/sale_pdf_quote_builder_demo.xml#L44-L51
[4]https://github.com/odoo/odoo/blob/8791cdcd89ea3cb56b1fac63b3e2ffbd2956a912/odoo/modules/loading.py#L89-L90
opw-6139555
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update improves the security of our bank account import process. It now only uses bank accounts designated as 'trusted' (with `allow_out_payment=True`) when matching partner information. This prevents potential errors and ensures data accuracy during bank account retrieval.
Original PR description
Restrict the matching domain to bank accounts with `allow_out_payment=True` so that only trusted bank accounts are used when retrieving a partner from a bank account number
This update fixes an issue where product matching by name was incorrectly associating products across multiple lines in imports. The fix adds a necessary cache key, ensuring that products are matched accurately based on their unique characteristics, preventing incorrect product assignments during import processes. This improves data integrity and import accuracy.
Original PR description
**PROBLEM** When retrieving a product by name, there is no cache_key for the search_method criteria. This leads to the cache_key frozendict being an frozen dict with None values. This means, once we retrieve a first product with the search_method criteria, all following product will match its cache_key, so we ends up associating a product to all subsequent lines, even if they don't have anything in common. **STEP TO REPRODUCE** 1. Create a product with the name: "CASTELTORRE MERLOT DELLE VENEZIE 75CL 10,5i" (it's important the name is not exactly matching) 2. Import the xml which is attached to the bug fix ticket. 3. Notice the product column on all the lines after a certain point have the CASTELTORRE product, even though the corresponding line in the ubl is for another product. opw-6227280
This update fixes a minor inconsistency in Polish VAT invoice calculations (l10n_pl_edi) related to unit prices. Increasing the precision of the unit price field ensures that the total without tax accurately reflects the invoice amount, aligning with FA(3) format requirements. While technically valid, this change improves invoice accuracy and data consistency.
Original PR description
**STEP TO REPRODUCE** 1. Create an invoice with a unit price of 10.005 and qty of 2. 2. Send the invoice to ksef. 3. Open the xml and notice P_9A (unit price) is 10.00 and P_11 (total without tax) is 20.01 Which is inconsistent (10.00 * 2 =/= 20.01). This PR increase the decimal places of P_9A to 8 digits which is the maximum allowed by the FA(3) format. Note that Ksef doesn't verify the untaxed unit price * quantity = total without tax, so the invoice we send are technically valid. However, it's best to generate invoice where the numbers add-up. opw-6203896