Wednesday, June 24, 2026
16 changes · saas-19.1
New functionality added to Odoo
This update introduces on-demand printing of kitchen order tickets directly from the kitchen station. When an order moves to a defined stage, the system automatically generates and prints a KOT. The tickets now include barcodes for efficient scanning and streamlined order processing.
Original PR description
*: pos_restaurant_preparation_display, pos_urban_piper In this commit: ------------------- - Introduced functionality to print KOTs on demand from the kitchen. - Added support for automatic printing when an order is moved to a configured stage. - Added barcodes to KOTs printed from the kitchen, allowing kitchen staff to scan them and directly move the order to the next stage. task: 6131467 Community PR: https://github.com/odoo/odoo/pull/266273
This update enables automatic receipt of vendor bills from the Hungarian tax authority (NAV) via their API. A new 'Sync with NAV' button allows users to schedule bill retrieval based on a date range, and supports both API integration and direct XML uploads for seamless invoice processing. This improves efficiency and accuracy for Hungarian businesses.
Original PR description
In Hungary, we are already sending invoices to NAV(hungarian tax authority). Now this module `l10n_hu_edi_receive` provides functionality of receiving vendor bills through its API and also adds XML…
In Hungary, we are already sending invoices to NAV(hungarian tax authority). Now this module `l10n_hu_edi_receive` provides functionality of receiving vendor bills through its API and also adds XML importer for Hungarian localization. A button `Sync with NAV` is added in vendor bills list view, which opens a wizard where you can select time period and all bills uploaded between that time are fetched from NAV's API. Also directly uploading XML is also supported in the format NAV supports. Flow:- - After selection of time range, we call `queryInvoiceDigest` endpoint with that range and it returns a list of digests(consider each digest as separate invoice) but this digests contains only meta data not all details. - Now for each digest we call `queryInvoiceData` endpoint which returns xml response with `QueryInvoiceDataResponse` as root node. This xml contains some meta data and `InvoiceData` node which has a base64 string, when we decode that string we get an xml with `InvoiceData` as root node and this xml contains all details of the invoice, we parse both these details and create bills and refunds. Also xml importer supports any of the `InvoiceData` or `QueryInvoiceDataResponse` xml. NAV Documentation: https://onlineszamla.nav.gov.hu/files/container/download/2025.10.09.%20EN_Online%20Invoice%20System%203.0%20Interface%20Specification%20.pdf task-5237910 Forward-Port-Of: odoo/odoo#240919
This update adds the ability to generate invoice PDF reports in multiple formats (Original, Duplicate, Triplicate) to comply with government regulations regarding GST documentation. Users can now print two or three copies of invoices with distinct titles, catering to different recipient types like transporters and suppliers. This ensures accurate record-keeping and adherence to tax requirements.
Original PR description
The Goverment specifies that invoice should be printed in different formats as per the different parties the invoice is been given to. Invoice should be marked as "Original" for receiver's copy. Invoice should be marked as "Duplicate" for transporter's (incase of goods supply) or supplier's copy. Invoice should be marked as "Triplicate" for supplier's (incase of goods supply) copy. This commit adds two new report actions, for Duplicate and Triplicate on invoice, visible in the Print section under the gear icon. When user prints Duplicate, 2 copies will be printed and for Triplicate, 3 copies will be printed at once, with different titles set on each copy of invoice. task-5899610 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270813
Enhancements to existing features
This update streamlines the process of printing preparation tickets from the kitchen within the Point of Sale system. By consolidating common code, the system avoids duplication and ensures a more efficient workflow. This change enhances the speed and reliability of order fulfillment.
Original PR description
In this commit: ------------------- - Moved common internally used methods to shared logic to avoid duplicating the same code multiple times task: 6131467 Enterprise PR: https://github.com/odoo/enterprise/pull/118286
Resolved issues and error corrections
This update fixes an error that prevented users from correctly processing credit notes with the 'P10' business process type in the Croatian e-invoicing module. The fix ensures compliance with Croatian tax authority regulations, allowing for accurate reporting of credit note corrections. This update resolves a restriction that was preventing the correct generation of e-invoices.
Original PR description
**Steps to reproduce:** * Install the Croatian e-invoicing module (**l10n_hr_edi**). * Set up a Croatian company and a Croatian customer partner (with OIB and VAT configured). * Create a customer…
**Steps to reproduce:** * Install the Croatian e-invoicing module (**l10n_hr_edi**). * Set up a Croatian company and a Croatian customer partner (with OIB and VAT configured). * Create a customer invoice and post it. * Create a credit note from that invoice via **Credit Note** button. * On the credit note, change **Business Process Type** from `P9` to `P10: Issuing a corrective invoice`. * Save the credit note. **Observed behavior:** * Saving fails with: "Business Process Type P9 can only be used with credit notes and vice versa." * The error occurs even though P10 is a valid process type for credit notes according to the Croatian tax authority specification. **Cause:** * The `_check_l10n_hr_process_type` constraint used an XOR-style boolean check: `(process_type == 'P9') == (move_type != 'out_refund')`. * This enforced an exclusive P9 ↔ out_refund mapping, making P9 the **only** allowed process type for credit notes and blocking P10 entirely. * Per the Croatian tax authority specification, P10 (corrective invoice) is explicitly valid for credit notes: full cancellations report negative quantities/amounts, and partial corrections may report either positive or negative values. **Fix:** * Replace the XOR constraint with two independent, clearly-scoped rules: - P9 may only be used on credit notes (`out_refund`). - Credit notes must use either P9 or P10. * Add P10 UBL type code mapping in `_ubl_add_credit_note_type_code_node()`: P10 credit notes now emit `CreditNoteTypeCode 384` (Corrected Invoice, UNTDID 1001) instead of falling through to the default 381. opw-6128955 - Official Croatian Information Intermediary: https://portal.moj-eracun.hr/blog/kako-stornirati-eracun/ - Croatian Tax Authority (FAQ on fiscalization and e-invoicing): https://porezna-uprava.gov.hr/UserDocsImages/Fiskalizacija/Fiskalizacija_eRacun/Pitanja%20i%20odgovori%20vezani%20uz%20Zakon%20o%20fiskalizaciji.pdf Forward-Port-Of: odoo/odoo#266288
This update significantly speeds up the calculation of future timesheets based on public holidays. The previous process was slow and inefficient, especially with many holidays set for the future. This change optimizes the calculation process, resulting in faster timesheet generation and improved system performance.
Original PR description
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several…
**Problem:** When creating a new employee, the future timesheets due to public holidays are computed. If the number of public holidays is large (i.e. if the user creates them for each year, several years in the future), then it takes excessively long and the action may not complete. **Cause:** The pytz method `localize` and comparing times with non-static timezones is done repeatedly and unnecessarily which becomes costly with more records. **Solution:** Only localize the time when absolutely necessary (determining the date of the leave in the calendar timezone). **Performance Stats:** |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |100 |3.1s |393 |0.8s |117 | |1,000 |22.3s |2,090 |1.5s |183 | |10,000 |Timeout |N/A |6.7s |541 | opw-6087422 Forward-Port-Of: odoo/odoo#269876 Forward-Port-Of: odoo/odoo#263953
This update corrects an error in the generation of E-Way Bills when prices include tax. Previously, the system incorrectly calculated tax amounts, leading to inaccurate E-Way Bill documents. The fix ensures that tax is properly accounted for, producing correct amounts for tax-included sales.
Original PR description
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create…
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create a Sales Order (e.g. unit price 300, qty 600, 18% GST) and confirm the Delivery Challan/Delivery Order. * Generate an E-Way Bill from the Delivery Challan. **Observed behavior:** * The Taxable Amount and Total Invoice Amount are displayed incorrectly in the generated E-Way Bill, including both the printed document and the JSON. * The `ewaybill_price_unit` shows the tax-excluded price (e.g. 254.24) instead of the original tax-included price (300), leading to a double tax exclusion when `compute_all` processes it. **Cause:** * `_l10n_in_get_product_price_unit` in both `l10n_in_sale_stock` and `l10n_in_purchase_stock` unconditionally used `price_subtotal / qty` to compute the E-Way Bill price unit. `price_subtotal` is always tax-excluded, so for tax-included prices, the tax was already stripped. * `_l10n_in_tax_details_by_stock_move` then passed this already tax-excluded price to `compute_all` with taxes that have `price_include=True`, causing `compute_all` to strip the tax a second time (e.g. 254.24 / 1.18 = 215.46 instead of the correct 254.24). **Fix:** * Check whether any of the line's taxes have `price_include` set. If so, use `price_total / qty` (which preserves the tax-included price) so that `compute_all` can correctly extract the tax. Otherwise, continue using `price_subtotal / qty` as before. opw-6273101 Forward-Port-Of: odoo/odoo#271492 Forward-Port-Of: odoo/odoo#268504
This update corrects a rounding error in how overtime durations are calculated, which previously caused overlapping time entries. The fix ensures accurate back-projection of work entries, preventing overlaps and guaranteeing correct overtime tracking. This improves the reliability of time and attendance data.
Original PR description
__Issue:__ `duration` is rounded to 3 decimals (~1.8s drift) while `time_stop` is exact, so the back-projected start could land before midnight on overnight overtime or middle of the day causing overlaps with the previous line Example: - time_start = 03/05 00:00:00 - time_stop = 03/05 07:07:14 actual duration 7h07m14s gets stored as `duration = 7.121` (= 7h07m15.6s) after `round(_, 3)`. Back-projection yields `datetime_start = 07:07:14 - 7.121h = 02/05 23:59:58`, overlapping by ~2s with the prior line ending at `02/05 23:59:59.999`. __Fix:__ Sort lines by `time_stop` within each date and clamp `datetime_start` to the previously emitted interval's stop when the two intervals genuinely intersect. opw-6170828 Forward-Port-Of: odoo/enterprise#116565
This update ensures that partner data created in the POS system is automatically synchronized with the latest information from the DIAN government service after a refresh. Previously, changes weren't reflected immediately, but this fix corrects this issue by updating the POS data during the refresh process. This improves data accuracy and compliance.
Original PR description
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh…
Step to reproduce: - install l10n_co_dian and pos - open pos and click on create a new partner from partner list - enter name ex. "temp", identification number, click on form - notice a `refresh icon` is visible: click on it. Observation: - the dialog is closed and partner is selected with "temp" name Expected: - with valid government credentials and a valid identification number, the refresh action should also update the partner data on the POS side Cause: - the refresh button triggers the `button_l10n_co_dian_refresh_data` action, which fetches the legal name and email from the government service - although the backend record is correctly updated, the new values are not immediately synchronized with the POS - when the refresh button is clicked, editPartner() first triggers `web_save` using the temporary "temp" name and immediately reads the partner data afterward - the refresh action executes later and updates the contact with the fetched legal information, but the POS is not aware of these subsequent changes Fix: - read the data again if there is any update caused by this action. - this is done by overriding `afterExecuteActionButton` of FormController class opw-6198035 Forward-Port-Of: odoo/enterprise#117527
This update resolves an issue where Italian POS systems using specific characters in product or payment names would cause printing errors. The fix replaces unsupported characters with spaces, aligning with EPSON fiscal printer documentation to ensure proper printing functionality. This prevents incomplete order prints and improves the Italian POS experience.
Original PR description
Steps to reproduce: - Setup an Italian fiscal printer - Modify the name of a product to use the non-blocking space character "\ "; - In the POS, create an order with the product. Error: the fiscal device will stop midway in the printing process and return an incomplete response to the frontend. The issue can also be reproduce if the character is included in the payment method name or the POS config name. Solution: When formating the xml command, replace all non-supported character by a space character. The non-supported character list is provided by the official [EPSON fiscal printer documentation](https://support.epson.net/setupnavi/?PINF=bsmanual&OSC=WS&LG2=EN&MKN=FP-90III%20RT) in the document "ePOS Fiscal Print Solution Development Guide". Other: Rename the file "dispaly_text.xml" to "display_text.xml". [opw-6244089](https://www.odoo.com/odoo/project/49/tasks/6244089) Forward-Port-Of: odoo/enterprise#121248 Forward-Port-Of: odoo/enterprise#120169
This update clarifies Redsys payment errors by mapping their technical codes to understandable messages. Previously, errors were difficult to diagnose, making it hard to resolve payment issues and provide accurate information to customers. This change improves the reliability and transparency of Redsys payments within Odoo.
Original PR description
Raw Redsys response codes were not human-readable, making it hard to diagnose failed transactions or provide meaningful feedback. See: https://pagosonline.redsys.es/desarrolladores-inicio/integrate-con-nosotros/parametros-de-entrada-y-salida/#tablepress-11_wrapper --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269968
This update resolves an issue where delivery dates set on sales orders weren't consistently reflected in manufacturing orders, leading to incorrect deadlines. The fix ensures that delivery dates are properly propagated to finished moves during quantity changes, allowing for accurate scheduling and merging of production steps. This improves order fulfillment accuracy.
Original PR description
Steps to reproduce: - Create a storable product with a BoM, routes MTO + Manufacturing, costing method FIFO + Perpetual (at invoicing) - Confirm a sale order for 1 unit → a manufacturing order is…
Steps to reproduce: - Create a storable product with a BoM, routes MTO + Manufacturing, costing method FIFO + Perpetual (at invoicing) - Confirm a sale order for 1 unit → a manufacturing order is created - Set a Delivery Date on the SO (Other Info tab) - Increase the SO line qty to 2 - Validate the MO → traceback on finished_move.ensure_one() Problem: When a delivery date is set on the SO, it propagates to the MO's finished move via date_deadline. However, `production.date_deadline\ was not updated (guarded by `if not production.date_deadline`) because the MO already had a deadline set at planning time: https://github.com/odoo/odoo/blob/19.0/addons/mrp/models/mrp_production.py#L476 When the SO qty then increases, change_production_qty copies the finished move to create a delta move. That delta move receives production.date_deadline (the stale planning date) instead of the delivery date, so the two finished moves end up with different deadlines and cannot be merged: https://github.com/odoo/odoo/blob/19.0/addons/mrp/wizard/change_production_qty.py#L43 Solution - always update production.date_deadline from its finished moves - link the new delivery move to the finished move after the qty wizard runs so it gets reserved after MO validation opw-6273076 Forward-Port-Of: odoo/odoo#269405
This update improves the speed and efficiency of automatically creating reconciliation rules for bank statements. The previous method consumed excessive memory and time when processing long payment references, leading to errors. This change uses a more efficient algorithm to find common substrings, significantly reducing processing time and memory usage, particularly for large transactions.
Original PR description
When setting an account to an account.bank.statement there is a step to automatically create a reconciliation rule/model if one does not exist already. To do so, we retrieve 5…
When setting an account to an account.bank.statement there is a step to automatically create a reconciliation rule/model if one does not exist already. To do so, we retrieve 5 account.bank.statement.lines and use them to define the reconciliation model config. A matching is done on the payment_ref of the account.bank.statement.lines by finding the longest common substring in the reference. ### Current Implementation The current algorithm does so by first generating all the possible substrings for all the payment_ref before doing the intersection between these sets and returning the max if `len(substring) >=10`. This is reasonable when the payment_ref follows either a SEPA communication national standard like the Belgian one or the Creditor Reference standard (ISO 11649). For transactions with large, unstructured communication with more than 100 chars, the method `_get_common_substrings` quickly overfill the memory, sometimes raising a MemoryErorr, and takes a significant amount of time. That's because the nested function `_generate_all_substrings` generates n*(n+1)/2 substrings, with n being the lenght of a payment_ref, called `label` in `generate_all_substrings`. ### Proposed Fix This commit introduces another algorithm to find the largest common substring. It starts by taking the two smallest labels to find their substrings intersection. We know that for an arbitrary collection of labels, the intersection of their substrings sets A ∩ B ∩...∩ Z is included in the intersection of any two substrings sets. The underlying assumption of the first step is that for an arbitrary collection of labels the intersection of the substrings sets of the two smallest labels will be the smallest intersection of any given pair of substrings sets. This won't hold true everytime and using a metric such as label similarity instead of shortest string might be better. But on average this should be good enough and it's easier to implement + it removes the need of preprocessing the labels to compute the similarity. The point of the new nested function `common_substrings` is to discard common substrings as we build them. Using the current `generate_all_substsrings` on either the smallest label or both smallest labels would still generate and store a lot of substrings, especially for large labels. By yielding the common substrings as we find them, the memory footprint is vastly reduced. Lastly, the next substring in the common_substrings iterable is only checked against the remaining labels if it's longer than the current match. This speeds up the whole process ### speedup In a customer database with some account.bank.statement.line with payment_ref > 500 chars, setting a specific account (code 4970) on transactions goes from MemoryError to < 1Mb memory consumption. Because of the memory consumption it was not possible to gather timing value on the current version. Testing the new algorithm in a shell and using as labels the 5 longest payment_ref in the customer database (831, 831, 1117, 1178, 1300 chars), averaging to 2000 chars once normalised, the average time to execute `_get_common_substrings` is 900 ms ± 10.3 ms. Forward-Port-Of: odoo/enterprise#118824
This update fixes an issue where work order durations were inaccurately calculated due to overlapping time entries. By filtering and merging productive and performance time, the system now provides a more precise duration for valuation purposes. Additionally, a fix was implemented to prevent timestamp issues during testing, ensuring accurate duration calculations.
Original PR description
[[FIX] mrp: calculate real duration excluding non-productive intervals](https://github.com/odoo/odoo/pull/248381/changes/fac6b2540a32a015f56085c2c27ba4281eb659cf) and deduplicating overlaps * Current…
[[FIX] mrp: calculate real duration excluding non-productive intervals](https://github.com/odoo/odoo/pull/248381/changes/fac6b2540a32a015f56085c2c27ba4281eb659cf) and deduplicating overlaps * Current Situation: Currently real duration is total duration of each time tracking which is not consistent with the time that use to calculate the cost for valuation , see https://github.com/odoo/odoo/pull/205154 .The real duration of a work order was incorrectly summing all time tracking entries regardless of their loss type, and using simple addition which double-counts overlapping intervals. * Solution: - Filter time entries to only 'productive' and 'performance' loss types, excluding 'availability' and 'quality' as they represent downtime/blocking time, not actual work duration. - Pool all productive and performance entries into a single Intervals call so that overlaps across both types are merged in one pass. Note: the enterprise17 implementation groups time entries by loss_type into separate buckets before calling Intervals, which means overlaps between 'productive' and 'performance' entries are not merged and get double-counted. Pooling both types together before the Intervals call avoids this. * This also fix: - Fix _set_duration to ensure newly created time entries start after the latest existing entry's end date. Without this, calling _set_duration twice in quick succession (e.g. in tests) produces two entries with overlapping timestamps, which Intervals correctly merges into one, causing the computed duration to be half the expected value. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#248381
A technical issue preventing users from creating opportunities on the website was resolved. The fix corrects a problem caused by recent code changes that incorrectly called a function needed to create elements on the page. This ensures the opportunity creation button is consistently available for users.
Original PR description
**Steps to reproduce:** - Install CRM app with website_crm_partner_assign - Go to the current user contact page > Partner Assignment - Set its partner level (e.g. Gold) - Go the `/my/opportunities` url of the website - Create opportunity button should be available - On click an error is raised: `TypeError: this.el.createElement is not a function` **Issue:** `createElement` is a method of `Document`, but it's called from a dom element after some `Interactions` refactoring. **Fix:** Properly call the method like before. related: https://github.com/odoo/odoo/commit/22e777c046521f3f89b62caa5876680beb7f5aba opw-6267473 Forward-Port-Of: odoo/odoo#268036
This update resolves an issue where the due date calculation for French payroll was inaccurate, particularly in November. It also corrects a technical error that prevented the system from properly processing certain records. These changes ensure accurate reporting and data processing for French businesses using this module.
Original PR description
- Fix due date calculation (returned month 0 if move date was in November) - Fix ensure_one error, avoid calling _deduce_country_code() on an empty recordset opw-6293701 Forward-Port-Of: odoo/odoo#270148 Forward-Port-Of: odoo/odoo#270003