Daily updates from Odoo
Wednesday, June 10, 2026
45 changes · saas-19.1
New functionality added to Odoo
This update expands Odoo's SII (Société d'Investissements et d'Innovation) functionality to include support for the Hacienda Foral de Navarra tax agency in Spain. It adds a new configuration option to handle the agency's specific invoice formatting and endpoint requirements, ensuring accurate tax reporting for businesses operating in the Navarra region. This improves compliance and supports a wider range of Spanish businesses.
Original PR description
The Hacienda Foral de Navarra uses the same SII XML format as AEAT but sends invoices to a different endpoint. Additionally, Navarra requires explicit XML namespace declarations in the SOAP envelope header, which the standard zeep serializer does not include by default. This adds the Navarra tax agency as a new option in the company SII configuration, defines its production and test endpoints, and injects the required namespaces in the request header when the Navarra agency is selected. task-5946583 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268438 Forward-Port-Of: odoo/odoo#263048
Enhancements to existing features
This update improves the D300 VAT report for Romanian businesses. The report's name has been changed to better align with local regulations and reporting requirements. This ensures accurate and compliant financial reporting for Odoo users in Romania.
Original PR description
Rename VAT report fom Romania task-5423935 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#252511
This update improves the generation of the D300 VAT report for Romania, aligning with the latest requirements from the ANAF (Romanian tax authority). It now creates an XML file, completing the necessary flow for submitting the report, ensuring compliance and accurate tax reporting.
Original PR description
Rename VAT report fom Romania and generate XML file to complete flow for D300 return complying with the latest ANAF specifications. https://static.anaf.ro/static/10/Anaf/Declaratii_R/300.html task-5423935 Forward-Port-Of: odoo/enterprise#109849
This update introduces a time limit for query profiling within Odoo. By tracking query execution times and periodically committing this data, we're improving the performance and reliability of the profiler tool. This ensures that profiling data is captured efficiently and doesn't negatively impact system performance.
Original PR description
Modify the query collector so that it add an entry before the query runs and updates the time after it runs. use the async collector periodic sampling to commit the profiler after a time limit. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268467 Forward-Port-Of: odoo/odoo#215034
Resolved issues and error corrections
This update optimizes how Odoo identifies default suppliers for purchase orders, significantly speeding up the process. By eliminating redundant queries, the system now responds much faster – reducing query counts by over 90%. This improvement directly impacts order processing speed and efficiency.
Original PR description
Currently, computing effective_vendor_id and supplier_id_placeholder presents N+1 query issues. Since every call to _get_default_rule() eventually triggers a _read_group() in _search_rule_for_warehouses(). However we can get rid of this entirely, since the subsequent call to _get_matching_supplier() with an empty values dict depends entirely on the product and not the rule. Another query is also avoided in _get_matching_supplier() which eventually calls ref(). ref() can be substituted with the private method since we are checking against the rule's existing route_id. Benchmark web_search_read by effective_vendor_id on 12,000 orderpoints | |Query Count|Exec Time| |------|-----------|---------| |Before|15,519 |17.46s | |After |722 |3.21s | opw-6186351 Forward-Port-Of: odoo/odoo#268315
This update prevents empty ICS calendar files from being generated when users attempt to add open shifts to their calendars. Previously, the system would create an empty file when a matching shift slot wasn't found. Now, the ‘Add to Calendar’ button is hidden and the ICS file is only generated when a valid shift slot is linked to an employee.
Original PR description
**Step:** - install planning - create a resource - create an open shift for a future date - in Gantt view: - publish shift and select the created resource - click “Publish & Send” - check the email and click “Add to Calendar” **Issue:** Currently, clicking “Add to Calendar” generates an empty ics file. **Reason:** During ics file generation, the planning token to find a slot using the planning date and employee. but, no matching slot is found, so the process returns an empty slot, resulting in an empty ics file. **Fix:** Generate the `planning_url_ics` only when a slot is linked with an employee. Otherwise, hide the “Add to Calendar” button and do not generate the ics file. Forward-Port-Of: odoo/enterprise#119838 Forward-Port-Of: odoo/enterprise#118978
This update resolves a bug where splitting orders incorrectly applied tax settings. When an order was split, the new order defaulted to the system's standard settings instead of the original order's tax configuration. This change ensures that split orders accurately reflect the tax settings of the original order, improving financial reporting and accuracy.
Original PR description
When splitting an order, `createNewOrder()` was called with no preset,so the new order silently fell back to the config's default preset. The moved orderlines kept their original price_unit and tax_ids while the new order header used the wrong fiscal_position_id and pricelist_id. Steps to reproduce: - Order with two products, switch to a preset that adds tax - Split, select one line, Payment, Validate - Pay the other line, Validate - open order in backend, first line has default price_unit and no tax, second line has correct price_unit and tax -opw-6246434 Forward-Port-Of: odoo/odoo#268862 Forward-Port-Of: odoo/odoo#268772
This update resolves a bug where cancelled journal entries were incorrectly displayed in the reconciliation view, preventing successful reconciliation and causing data inconsistencies. The fix removes a previous refactor that allowed draft entries, which inadvertently exposed cancelled entries. This ensures accurate reconciliation processes.
Original PR description
Issue: Cancelled journal entries were visible in the "Journal Items to Reconcile" view (action_move_line_posted_unreconciled) because the action domain had no filter to exclude them. This caused…
Issue: Cancelled journal entries were visible in the "Journal Items to Reconcile" view (action_move_line_posted_unreconciled) because the action domain had no filter to exclude them. This caused reconciliation failures, no reconciliation happened, and the cancelled record remained in the view. This regression was introduced during a refactor to allow draft entries in the reconciliation view, where the posted-state condition was removed from the domain: Enterprise commit: https://github.com/odoo/enterprise/commit/003cffabda7d91a6d10d58942ed972ca5e17366d As a result, cancelled journal items also became visible, causing reconciliation attempts to fail while the records remained in the view. Also, we are not allowed to reconcile cancelled move lines, and we already have the validation for this [here](https://github.com/odoo/odoo/blame/a236f67776616f6facdefb0117a6ffdde9b7c84c/addons/account/models/account_move_line.py#L2627) Issue is reproducible on runbot. Here is the video reference: https://drive.google.com/file/d/1ojIDxHn5Yst8gVFy8JyhwtJoDSSSJsmK/view?usp=sharing - OPW: 6247870 Forward-Port-Of: odoo/enterprise#119017 Forward-Port-Of: odoo/enterprise#118773
This update removes a duplicate button from the channel management interface. Previously, users encountered errors when attempting to copy channels, and this feature didn't provide a useful function. This change simplifies the channel management process and resolves a minor usability 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#268999
This update fixes a visual issue where the carousel display would sometimes become unstable when images were resized or changed. The fix uses a new monitoring system to ensure all carousel items maintain a consistent height, preventing layout problems and improving the overall user experience. This ensures a smoother and more reliable carousel display for website visitors.
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 fixes an issue where subtype information was lost when moving messages within Odoo. Now, users will see the subtype description in chatter, providing clearer context for conversations and improving message clarity. This enhancement ensures users have a complete view of message details.
Original PR description
Currently, when we move a message from one record to another, the subtype is cleared.Because of this, the description is not visible and the transferred record shows it as empty. In this commit, we append the subtype description into the message body.So the user can see the subtype description in chatter. task-6227750 Forward-Port-Of: odoo/odoo#265003
This update resolves an error that occurred when sending invoices with Danish VAT numbers via Peppol. Now, customers in Denmark can use VAT numbers without the 'DK' prefix, and the system will correctly generate the Peppol endpoint with the required prefix. This ensures invoices are processed correctly and avoids errors during international electronic invoicing.
Original PR description
Current behavior before PR: - Currently, when we include `DK` country prefix in the VAT number, it automatically computes the peppol endpoint with the `DK` prefix for customer from Denmark. - However, there are cases where the VAT number may not include `DK` country prefix, while the corresponding peppol endpoint still does. - In such situations, when sending an invoice via Peppol, the following error occurs: "Errors occurred while creating the EDI document (format: UBL BIS Billing 3.0.12): The VAT of the customer should be prefixed with its country code." Desired behavior after PR is merged: - Now customer from Denmark can have vat without country prefix `DK` and peppol endpoint with prefix `DK` and can send invoice via peppol. task-6119563 Forward-Port-Of: odoo/odoo#263262
This update resolves an issue where refund orders were generating duplicate invoice numbers for the Spanish tax authority (TicketBAI). The fix ensures unique invoice numbers are used for refunds, preventing rejection by the tax authority and streamlining the refund process. This improves compliance and reduces manual intervention.
Original PR description
Refund orders use a display name based on the original ticket. The rectificativa was then submitted with a duplicate Serie/NumFactura and rejected with TicketBAI error 5040. Steps to reproduce:…
Refund orders use a display name based on the original ticket. The rectificativa was then submitted with a duplicate Serie/NumFactura and rejected with TicketBAI error 5040. Steps to reproduce: ------------------- * Enable TicketBAI for a Spanish company with POS * Create an order and complete payment (TicketBAI sent) * Refund that order from the POS and complete payment * Open the new TicketBAI XML (downloadable on the order in the backend) > Observation: `CabeceraFactura` `NumFactura` matches the original sale; tax authority returns 5040 (duplicate invoice for same issuer/series/year). Why the fix: ------------ The TicketBAI document `name` was set from `pos.order.name`, so `_get_tbai_seq_from_name` extracted the same numeric part as the original sale. `l10n_es_edi_tbai.document` derives Serie/Num from `name` via `_get_tbai_seq_from_name`. Refund POS names intentionally echo the original order label, so we derive the document name from the same components as non-refund orders (`get_reference_last_part()`), which is unique per receipt. opw-6067965 Forward-Port-Of: odoo/odoo#257475
This update resolves a potential error in the Hong Kong payroll calculations. The fix prevents a division-by-zero issue that could occur when a resource calendar is missing or when an employee has zero hours per week. This ensures accurate payroll processing 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 the product image carousel wouldn't scroll correctly after a product variant was selected on the e-commerce site. The fix ensures that the carousel properly updates and responds to user interactions like scrolling, improving the shopping experience. This was caused by a technical glitch in how the system handles carousel updates.
Original PR description
Steps to produce: --- - Install `website_sale` module. - Create a product with a variant and add the images from the sale tab. - Go to the product on the e-commerce and change the variant. - Attempt…
Steps to produce: --- - Install `website_sale` module. - Create a product with a variant and add the images from the sale tab. - Go to the product on the e-commerce and change the variant. - Attempt to scroll through the product images (using the mouse wheel). Issue: --- - After changing a product variant on the eCommerce product page, attempting to scroll through the product images (using mouse wheel) has no effect. Root cause: --- - When a product variant is changed, `_updateProductImage` dynamically replaces the product image carousel DOM element (`#o-carousel-product`) by injecting new HTML and removing the old one. - The old CarouselProduct interaction instance remains in memory, causing a resource and event listener leak on the detached old DOM element. - The newly inserted `#o-carousel-product` element is ignored by the interaction service, meaning that the CarouselProduct interaction is never initialized on the new carousel. This leaves the new carousel static and unresponsive to user interactions. Solution: --- - Before replacing the carousel DOM node, manually notify the public.interactions service to clean up any active interactions on the old element. After the new DOM node is queried, start the interactions on the new element. opw-6229291 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265537
This update optimizes the performance of account reports when hovering over tables with many columns. Previously, hovering caused significant lag due to complex CSS calculations. This change reduces these calculations by targeting specific table cells, resulting in a smoother user experience.
Original PR description
Forward-Port-Of: odoo/enterprise#119242
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
This update streamlines spreadsheet document management by disabling versioning for spreadsheets and frozen spreadsheets. This reduces unnecessary data storage and improves performance, as spreadsheets already track their history through revisions. The change also hides the versioning action for these document types.
Original PR description
This PR consists of two commits. The first commit hides the Manage Versions action button for spreadsheet and frozen spreadsheet documents, since versioning is disabled for those records. The second commit is a backport of enterprise commit 0e319d0. It disables document versioning for spreadsheet and frozen spreadsheet documents, as spreadsheets already manage their history through spreadsheet revisions. This avoids creating unnecessary document history attachments when spreadsheet data is written or when a spreadsheet is copied. Task: [6236496](https://www.odoo.com/odoo/project/2328/tasks/6236496) Forward-Port-Of: odoo/enterprise#119689 Forward-Port-Of: odoo/enterprise#118484
This update ensures that descriptions for sale order lines created from deliveries now accurately reflect the product's description, rather than just the product name. Previously, a new line added to a delivery would lack a description in the related sale order. This improves data clarity and reporting accuracy.
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 functionality.
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 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 accurately reflects the payment amount with the correct currency precision, improving payment accuracy and reducing potential errors. This impacts vendor bill payments.
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 an issue where undoing the auto-plan feature would reset shift workloads, leading to inaccurate resource allocation. The change ensures that allocated hours remain consistent after undoing, allowing for more reliable planning and scheduling. This improves the accuracy of workload assignments.
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 an issue where tax calculations within Point of Sale (POS) were consistently showing positive tax base amounts, regardless of the actual tax amount. This resulted in inaccurate tax reporting in the accounting system. The fix ensures that tax base amounts accurately reflect the tax liability, providing correct financial reporting.
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 a bug in the Datev reporting process for German companies. Previously, untaxed invoice lines incorrectly inherited the Datev code from the preceding line, resulting in inaccurate reports. This change ensures that untaxed lines properly display an empty Datev code, aligning with correct accounting practices.
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, specifically when the scheduled delivery date was missing or set in the past. The change automatically adds one hour to the delivery date, 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
A bug was causing grouped payments to incorrectly link existing invoices with new ones. This update fixes the way payments are linked to invoices, ensuring that payments are accurately associated with the intended invoices, regardless of whether they are part of a grouped payment.
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 improves the overall customer experience.
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#268826 Forward-Port-Of: odoo/odoo#262412
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
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. This improves the responsiveness of the HR module for users.
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 fixes an issue where product descriptions weren't correctly appearing on manufacturing orders (MOs) created from Point of Sale (POS) orders. The change ensures that all product variants, especially those with custom attributes, have accurate descriptions displayed on MOs, aligning with how descriptions are handled in the standard sale module. This improves clarity and consistency for users managing orders.
Original PR description
**Steps to reproduce:** - Install pos_mrp - Make a BoM for a product - The product must have a custom attribute, of type always - Go to the PoS - Make a sale, with a customer, enable Ship Later - Go…
**Steps to reproduce:** - Install pos_mrp - Make a BoM for a product - The product must have a custom attribute, of type always - Go to the PoS - Make a sale, with a customer, enable Ship Later - Go to the created MO - The Custom Description field is not showing **Why the fix:** This fix was previously done by e53dae2 but it did not account for the other variants and only did the fix for the never attributes. This is because it seemed to work with other kinds of attributes until 19.0 We now also compute the move description if we have a custom attribute. We need the never variants to have a description as well, as it is done in the sale module. This commit basically aligns the behavior to the on done in the sale module. A test had to be changed, as we now write the description in a different way, to make it the same regardless of where the picking and moves were created from. We now won't see a difference on the MO between one created from the POS and one created through the sale module. opw-6169257 Forward-Port-Of: odoo/odoo#263350
This update resolves an issue where a specific configuration in the French VAT reporting module was generating an error. When the street address was short and 'street 2' was marked as false, an incorrect value ('False') was being written to the report's XML, causing a processing failure. This fix ensures accurate report generation and avoids potential disruptions.
Original PR description
When the street field is shorter than 30 char and street 2 is false, we end up with " False" in the xml, which will return an error in aspone. no task id Forward-Port-Of: odoo/enterprise#119718
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 adds a validation step to prevent this, ensuring that recurring products are only added when a valid subscription is present, improving data integrity and preventing unexpected errors.
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#119955 Forward-Port-Of: odoo/enterprise#107691
This update resolves a technical issue where removing the quantity input field on rental product pages caused a website error. The change was due to a recent architectural update that moved data evaluation logic directly into the website component, leading to a crash when the input field was removed. This fix ensures the website remains stable and functional.
Original PR description
Steps to reproduce: 1. Install website_sale_renting_planning 2. In rental module, create a product that is of type service and can be sold 3. Go to the website and remove the quantity selector input field from the page and save. Issue: `TypeError: Cannot read properties of null (reading 'dataset')` Why this happens: Following architectural changes in v19.1, the rental data evaluation logic was moved directly into the DaterangePicker component lifecycle. Commit 4e5f71d introduces a new method to where, during initialization (`willStart`), the component triggers `setAddQtyInputMax()` to update the dataset attributes of the quantity selector input box. If the quantity selector has been removed via the website customizer `querySelector` returns `null`, causing the assignment to crash. In v19.0, this logic lived in the `WebsiteSale` interaction, executing only during post-render UI event listener triggers which kept it safe. opw-6268945
This update fixes an issue where planned dates were lost when converting projects to project templates. The change ensures that the original planned dates are correctly copied to the new template, improving project tracking accuracy. This prevents data loss and ensures consistent project planning.
Original PR description
****Steps** to reproduce:** - Open a project with a planned date set. - Create Template of that project. - Observe the created project template. **Issue:** The planned dates of the project are lost when converting the project into a template. **Cause:** When we create a project template from a project, the project gets archived. Because a new project template record is created, and the start and expiration fields have copy=False, those dates are not being copied. **Fix:** Explicitly pass the planned date when copying the project, so the project template keeps the original planned date. task-5872500 Forward-Port-Of: odoo/odoo#269159 Forward-Port-Of: odoo/odoo#249411
This update fixes an issue where planned dates were lost when converting projects to templates. The change ensures that project templates retain the original planned dates, improving accuracy and usability for project management. This resolves a previous data inconsistency.
Original PR description
Steps to reproduce: -------- - Open a project with a planned date set. - Create Template of that project. - Observe the created project template. Issue: ---------- The planned dates of the project are lost when converting the project into a template. Cause: ----- When we create a project template from a project, the project gets archived.Because a new project template record is created, and the start and expiration fields have copy=False, those dates are not being copied. Fix: ------- Explicitly pass the planned date when copying the project, so the project template keeps the original planned date. task-5872500 Forward-Port-Of: odoo/enterprise#119921 Forward-Port-Of: odoo/enterprise#115035
This update prevents unnecessary placeholder images from being sent during menu synchronization. By only transmitting actual image URLs when images are defined, we've optimized the data being transferred, leading to faster menu updates and a smoother user experience. This change improves the efficiency of the Odoo Enterprise system.
Original PR description
This commit prevents placeholder images from being included in the menu sync payload and only sends `img_url` when an actual image is configured on the product or category. Task-6251430 Forward-Port-Of: odoo/enterprise#119883 Forward-Port-Of: odoo/enterprise#119482
This change resolves an issue where extremely long invoice reference strings in the general ledger report were causing wkhtmltopdf to generate bloated PDF files. By limiting the length of the reference string, we prevent the PDF from becoming excessively large and ensure reports generate reliably. This improves report performance and avoids 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 Forward-Port-Of: odoo/enterprise#118067