Daily updates from Odoo
Navigate
Branch
Saturday, June 27, 2026
69 changes
7 changes
New functionality added to Odoo
This update adds support for Belgium’s certified cash register requirements in POS restaurant workflows. It ensures sales, refunds, cash movements, reports, and related actions are properly recorded and signed for fiscal compliance, including support for training mode and error handling. It also extends the solution to related flows such as employee clock-in/out, loyalty rewards, self-ordering, deferred payments, and online orders so they follow the same certified process.
Original PR description
Note: this PR is a forward of https://github.com/odoo/enterprise/pull/96130 Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance…
Note: this PR is a forward of https://github.com/odoo/enterprise/pull/96130 Implement the Belgian Registered Cash Register (Caisse Enregistreuse Certifiée) v2 specification as required by FPS Finance for certified POS restaurant systems. The implementation is split into a core module and five bridge modules: l10n_be_pos_blackbox (main module): - FDM (Fiscal Data Module) communication layer that signs every fiscal event by sending a structured message to the blackbox device and receiving a hash + VSC counter in return. M110 (sale), M111 (refund), M112 (partial refund), M121 (order), M122 (cost-centre change), M123 (pre-bill), M130 (money in/out), M131 (drawer open), M140/M141 (work in/out), M150 (invoice), M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). M160 (copy), M180/M181 (X/Z turnover report), M182/M183 (user X/Z report), UC230 (sale correction). - Input generator that encodes all line-level fiscal data (PLU hash, VAT groups, price rounding, grouping IDs) according to the spec. - Fiscal receipt template (XML) that renders the blackbox hash, VSC counter, POS system identifier, and event sequence number on every printed receipt. - X/Z daily report views with fiscal totals per VAT category. - Training-mode support: activates the FDM training flag so the device does not count test transactions. - Inspect popup (debug) for examining raw FDM messages. - Error/warning popup system with traceback messages from the device. - LocalStorage queue to replay pending mutations after a network outage. - pos_config / pos_session overrides: enforce blackbox constraints (only EUR, no rounding, mandatory restaurant mode, etc.), manage device pairing, and accumulate per-session fiscal counters. - Extensive unit-test suite: >6 000 lines covering the input generator's grouping-ID logic, price-consistency rules, and every mutation type against golden JSON fixtures. - Browser tour tests (oracle + regression tours). l10n_be_pos_blackbox_hr: - Clock-in / clock-out flows for employees trigger M140/M141 work in/out mutations; employee INSZ/NISS number is required and stored on hr.employee; pos_session accumulates per-employee work records. l10n_be_pos_blackbox_loyalty: - Gift-card and discount reward lines are mapped to the correct MPV fiscal codes (UC260/UC261); loyalty products are flagged so the input generator can calculate their contribution to the signed total correctly. l10n_be_pos_blackbox_self_order: - Intercepts self-order confirmation on kiosk screens to sign the order with the FDM before the confirmation page is shown; adds a controller to expose the required blackbox data to the kiosk frontend. l10n_be_pos_blackbox_settle_due: - Handles the "settle due" payment flow: products used to represent deferred payments are flagged and treated as zero-VAT lines in the signed message. l10n_be_pos_blackbox_urban_piper: - Patches the Urban Piper ticket-screen and pos_store so that online orders routed through Urban Piper are also signed before finalisation. community PR: https://github.com/odoo/odoo/pull/272155 task-id: 5864870
Enhancements to existing features
The Point of Sale has been updated to support the new Belgian blackbox v2 requirements. This mostly restructures internal POS flows so local Belgian rules can control payment, cashier, receipt, and order-synchronization behavior without disrupting standard use.
Original PR description
Note: this PR is a forward of https://github.com/odoo/odoo/pull/229692 Refactor several POS core methods into overridable hooks so that l10n_be_pos_blackbox (v2) can intercept and extend critical…
Note: this PR is a forward of https://github.com/odoo/odoo/pull/229692 Refactor several POS core methods into overridable hooks so that l10n_be_pos_blackbox (v2) can intercept and extend critical flows to implement the new blackbox requirements. point_of_sale: - pos_store.js: extract posBackOnline(), openCashbox(), getSelfOrderToPrint(), and resetCashier() as dedicated methods; setCashier() now returns a boolean; preSyncAllOrders() now returns the orders array, and the sync loop skips an order when it returns falsy (allows blackbox to block premature syncing); add orderReceiptComponent class property so the receipt component can be substituted by submodules. - order_payment_validation.js: extract canPrintReceipt getter (makes it overridable); fix absolute import path for error_handlers; fix typo "occured" → "occurred". - pos_session.py: load product.template / product.product before account.tax in _load_pos_data_models to satisfy the blackbox data dependency order; include account_move id in the invoice list returned by the session sales-details report. pos_hr: - Split setCashier() into setCashier() + setCashierUpdateSession() so the session-update side-effect can be called independently by the blackbox during clock-in/out flows. Return true from setCashier() consistently with the base method. pos_loyalty: - Override displayPrice on order lines so gift-card trigger products always display a positive price, even when the order is a refund. pos_restaurant: - Refactor mergeOrders() into _mergeOrders() + _mergeLines() private helpers; add getLinesToMerge() hook so blackbox can filter which lines participate in a merge; mergeOrders() now returns the destination order; extract syncRestoredOrders() for overridability; replace the while-loop-with-guard-counter with a plain for-of loop. pos_self_order: - Add orderReceiptComponent property; extract handleKioskSessionStatusChange() so the kiosk status-change behaviour can be overridden by the blackbox self-order bridge. enterprise PR: https://github.com/odoo/enterprise/pull/121799 task-id: 5864870 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This change fixes an access issue that could block database users from synchronizing their databases. It ensures the correct permission check is applied so the process completes without unnecessary errors.
Original PR description
The aim of this commit is to allow the databases_user to synchronize their databases. Context: The commit https://github.com/odoo/odoo/commit/846eb51a02baaf2e4f6e6780f8d0ceb23322c38b introduced a change of behavior in stable that performs some more check on access rights. Before this commit: The checks introduced by the commit resulted in an access error. There wasn't any groups on the action itself resulting in a check of the access right "write" on the model. As the model is `project.project` and a databases_user might not be granted write access on the project itself, it resulted in an access error. After this commit: The flow continues smoothly. As the action has now a group set on it, this is checked first and match the proper access right. opw-6329058 Forward-Port-Of: odoo/enterprise#121589
This update prevents a traceback that could appear when users open a billing target in Timesheets. It ensures the required leave information is available so the screen opens correctly and the billing rate indicators continue to work as expected.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` and `current_leave_id` field, change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value. Forward-Port-Of: odoo/enterprise#121888 Forward-Port-Of: odoo/enterprise#121571
This update makes sure amounts sent to Cashmatic payment machines are always calculated using a fixed 100-cent unit. It prevents mismatches with currencies that do not follow the machine’s expected decimal handling, helping payments be processed correctly.
Original PR description
Despite its API description, the Cashmatic machine always operates with 2 decimal places regardless of the currency. According to the Cashmatic head developer, only 2-decimal currencies are supported, with the sole exception of Chilean Peso (CLP) which has no decimals but is still handled with a fixed 100 cents-per-unit factor. Replace `Math.pow(10, currency.decimal_places)` with a `CENTS_PER_UNIT` constant set to 100 to make this assumption explicit. 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#272465
This update makes the website carousel walkthrough more dependable by using a clearer, deterministic way to confirm the slide URL. It helps prevent occasional test failures, which improves the reliability of website-related checks.
Original PR description
Make the step deterministic by committing the URL with edit and pressing Tab in the input instead of relying on a dropdown click. runbot-241089 Forward-Port-Of: odoo/odoo#272374
Subscription reports now exclude non-recurring products when calculating recurring revenue totals such as MRR and YRR. This prevents inflated figures if someone removes the default recurring filter in the reporting view.
Original PR description
While investigating a support ticket, we noticed that in subscription reports, recurring revenue values (MRR and YRR) are implicitly calculated for non-recurring products. This doesn't cause a direct problem when using the default search domains applied in Subscription > Reporting > Subscription > Pivot view, because a "Recurring" filter is pre-applied. But if the end user removes said filter, they might accidentally fudge the MRR and YRR numbers because the non-recurring products will contributed to the relevant grouping sums. We fix this by adding a CASE clause to explicitly ignore non-recurring products when calculating the report field for MRR and YRR , i.e. only consider `t.recurring_invoice = TRUE`. OPW-6315091 Forward-Port-Of: odoo/enterprise#121566
9 changes
Resolved issues and error corrections
Shop Floor now sorts manufacturing orders more consistently by putting unplanned work orders after planned ones. This fixes a display issue where orders without a scheduled start date could incorrectly appear ahead of orders that were already planned, making priorities clearer for operators.
Original PR description
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will…
## Problem In shop floor, MOs with unplanned work orders get sorted before MOs that have planned operations, which contradicts the normal nulls last sorting for work orders. ## Solution We will update the sorting logic in the MrpDisplay component to more gracefully handle falsy date_start values, sorting them to the end. ## Steps to reproduce (runbot 19) 1. Create 2 MOs with an operation (work order) involving a work center, we'll call them A and B. 2. Open Shop Floor and open the work center that the MOs' work orders belong to, and note they are ordered A, B (this is fine, neither are planned so the precedence falls back to id 3. Go back to MO B and plan it. This should give it precedence in Shop Floor 4. Under the work center in Shop Floor, note that the MOs are still ordered A, B, despite B's work order having a start date and A's work order not having one To further motivate this being unintended, you can go to Manufacturing > Operations > Work Orders, and you'll see MO B's work order sitting at the top of the list. opw-6303323 Forward-Port-Of: odoo/enterprise#121693
This change fixes an editor issue where the cursor could jump to the edge of a template block when deleting text inside it. Editing email templates is now smoother and more predictable, reducing the chance of losing your place while making small changes.
Original PR description
## Problem:
`<t>` elements are classified as self-closing, even if they aren't used that way in a mail template. If you press backspace in the editor on some plain text that happens to be inside a `<t></t>` block, the editor would prevent the cursor from being placed back inside the block after merging because of `normalizeSelfClosingElement`. The result is the cursor being left on the outside edge of the block.
## Solution:
We will remove "T" from the list of self-closing tags.
## Steps to replicate (runbot v18):
1. Open an email template (Purchase: Purchase Order)
2. Place your cursor in some text inside a t-if element ('The receipt is expected for...'). Press backspace. Your cursor will snap to the end of the t-if block.
opw-6124284
Forward-Port-Of: odoo/odoo#266816This fix prevents a traceback when users open a Billing Time Target from Timesheets. It restores the expected screen flow so users can review billing targets without interruption.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` field, change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value. Forward-Port-Of: odoo/enterprise#121571
This update prevents an error when sending Colombian debit notes to DIAN. The system now leaves out an unnecessary reference field for this document type, so debit notes can be generated and submitted successfully.
Original PR description
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on…
Issue: Sending Debit Notes to a tax authority can cause the following error: "ValueError: The following child node is not defined in the template: DebitNote/cbc:BuyerReference" Steps to reproduce on any database with DIAN and Colombian localization: 1. Create a new "Sales" type journal. Then, check the checkbox “Nota de Debito”. 2. Find a res.partner with a ref field, or add a ref field to any partner. 3. Make an invoice using the partner found in step 2. Ensure it uses a tax. Confirm it. 4. Send that invoice to DIAN. 5. Create a Debit Note for that invoice. Use the journal created in step 1. 6. Add a product, price, and tax to the debit note. Confirm it. 7. Send the debit note to DIAN. Explanation: The `_add_invoice_header_nodes` method on the AccountEdiXmlUbl_21 model adds a BuyerReference node unconditionally. (See account_edi_xml_ubl_21.py.) But the DebitNote XML template does not include a BuyerReference element (see ubl_21_debit_note.py). This caused a ValueError when assembling the XML for debit note documents. Solution: The fix overrides this in the Colombian localization by clearing the BuyerReference value when the document type is "debit_note". That way, the node is omitted from the output. opw-6181039 Forward-Port-Of: odoo/enterprise#121458 Forward-Port-Of: odoo/enterprise#121422
When a new language is added, the DIAN email templates will now also appear translated instead of staying in the original language. This improves the user experience for Colombian businesses using DIAN documents, especially for teams working in multiple languages.
Original PR description
### Issue: When installing a new language on a database with `l10n_co_dian`, the DIAN email templates are not translated Languages already installed when `l10n_co_dian` is installed are correctly…
### Issue: When installing a new language on a database with `l10n_co_dian`, the DIAN email templates are not translated Languages already installed when `l10n_co_dian` is installed are correctly translated, as the copy happens at that moment Only languages installed afterwards are affected ### Cause: The DIAN email templates are created dynamically via `_create_dian_mail_templates` as copies of the `account` templates Because they are created at runtime, no translations exist for their XML IDs in the `l10n_co_dian` `.po` files The `TranslationImporter` finds nothing to import for them The fix hooks into `_load_module_terms` to sync translations from the source `account` templates to the DIAN ones whenever a new language is installed `TranslationImporter.save()` is used without `force_overwrite`, so existing translations on `noupdate` records are never replaced This is the standard way to push translations while preserving any manually modified values ### Notes: Languages installed before this fix are not updated Only newly installed languages will get the synced translations ### Steps to reproduce: - Install `l10n_co_dian` - Enable Developer Mode in Settings - Install any language (e.g. `fr_FR`) - Go in Settings > Technical > Email > Email Templates - Search for DIAN and open Invoice or Credit Note Before the fix, the DIAN invoice and credit note templates had untranslated name, description and body_html opw-6269979 Forward-Port-Of: odoo/enterprise#120855
This update fixes an access problem that could block database users from syncing their databases. It ensures the right permission check is applied so the process continues without unnecessary errors.
Original PR description
The aim of this commit is to allow the databases_user to synchronize their databases. Context: The commit https://github.com/odoo/odoo/commit/846eb51a02baaf2e4f6e6780f8d0ceb23322c38b introduced a change of behavior in stable that performs some more check on access rights. Before this commit: The checks introduced by the commit resulted in an access error. There wasn't any groups on the action itself resulting in a check of the access right "write" on the model. As the model is `project.project` and a databases_user might not be granted write access on the project itself, it resulted in an access error. After this commit: The flow continues smoothly. As the action has now a group set on it, this is checked first and match the proper access right. opw-6329058 Forward-Port-Of: odoo/enterprise#121589
This update makes sure amounts sent to Cashmatic cash machines are calculated in the fixed format they actually support. It prevents incorrect payment values when different currencies are used, including the special case of Chilean Peso.
Original PR description
Despite its API description, the Cashmatic machine always operates with 2 decimal places regardless of the currency. According to the Cashmatic head developer, only 2-decimal currencies are supported, with the sole exception of Chilean Peso (CLP) which has no decimals but is still handled with a fixed 100 cents-per-unit factor. Replace `Math.pow(10, currency.decimal_places)` with a `CENTS_PER_UNIT` constant set to 100 to make this assumption explicit. 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#272465
Subscription reports now ignore non-recurring products when calculating monthly and yearly recurring revenue. This prevents MRR and YRR totals from being overstated if users remove the default recurring-only filter in the report.
Original PR description
While investigating a support ticket, we noticed that in subscription reports, recurring revenue values (MRR and YRR) are implicitly calculated for non-recurring products. This doesn't cause a direct problem when using the default search domains applied in Subscription > Reporting > Subscription > Pivot view, because a "Recurring" filter is pre-applied. But if the end user removes said filter, they might accidentally fudge the MRR and YRR numbers because the non-recurring products will contributed to the relevant grouping sums. We fix this by adding a CASE clause to explicitly ignore non-recurring products when calculating the report field for MRR and YRR , i.e. only consider `t.recurring_invoice = TRUE`. OPW-6315091 Forward-Port-Of: odoo/enterprise#121566
This update makes the website carousel editing test more reliable by using a direct, consistent way to confirm the edited link. It reduces the chance of the tour failing randomly, which helps keep website updates and automated checks stable.
Original PR description
Make the step deterministic by committing the URL with edit and pressing Tab in the input instead of relying on a dropdown click. runbot-241089 Forward-Port-Of: odoo/odoo#272374
5 changes
Resolved issues and error corrections
This change prevents an error that could happen when users add properties to a record. The system now waits for the property data to finish loading before showing the properties panel, making the action more reliable.
Original PR description
Description of the issue/feature this PR addresses: This error occurs when a model has properties and a `computed` field or `onchange` method depends on them. `record.update()` is asynchronous. When…
Description of the issue/feature this PR addresses: This error occurs when a model has properties and a `computed` field or `onchange` method depends on them. `record.update()` is asynchronous. When an onchange or computed field is triggered, an additional request is sent to the server, increasing the time required to complete the update. See: https://github.com/odoo/odoo/blob/727fe7412bb37c1664106625e248264d2aab6809/addons/web/static/src/model/relational_model/record.js#L1207-L1211 However, `PropertiesField` is rendered before the `update` is completed. See: https://github.com/odoo/odoo/blob/727fe7412bb37c1664106625e248264d2aab6809/addons/web/static/src/views/fields/properties/properties_field.js#L86 As a result, the property labels are not yet available and the following traceback is raised: `TypeError: Cannot read properties of undefined (reading 'getRootNode') ` After this commit, the update is awaited before rendering PropertiesField, ensuring that the property labels are available. **Steps to reproduce:** 1. Install the example module. [project_task_property.zip](https://github.com/user-attachments/files/29138424/project_task_property.zip) 2. Open or create a project task. 3. From the Action menu, click `Add Properties`. The error is raised. <img width="1520" height="956" alt="image" src="https://github.com/user-attachments/assets/a3051ddf-5af0-4d3a-8ff7-c3fb4f7a69d2" /> TT63331 @Tecnativa @pedrobaeza --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272571 Forward-Port-Of: odoo/odoo#271082
This change fixes a traceback that could appear when users open a Billing Time Target in Timesheets. It restores the missing employee leave information needed by the view, so users can access billing rate indicators without the page breaking.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` field, change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value. Forward-Port-Of: odoo/enterprise#121571
This change ensures amounts sent to the Cashmatic payment machine are always calculated using the format the device actually expects. It prevents incorrect payment values from being transmitted in currencies where the previous logic could have used the wrong decimal conversion.
Original PR description
Despite its API description, the Cashmatic machine always operates with 2 decimal places regardless of the currency. According to the Cashmatic head developer, only 2-decimal currencies are supported, with the sole exception of Chilean Peso (CLP) which has no decimals but is still handled with a fixed 100 cents-per-unit factor. Replace `Math.pow(10, currency.decimal_places)` with a `CENTS_PER_UNIT` constant set to 100 to make this assumption explicit. 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#272465
This update makes the website carousel walkthrough more reliable by using a deterministic way to confirm the slide URL. It reduces the chance of the test failing unpredictably, helping keep website testing stable and trustworthy.
Original PR description
Make the step deterministic by committing the URL with edit and pressing Tab in the input instead of relying on a dropdown click. runbot-241089 Forward-Port-Of: odoo/odoo#272374
Recurring revenue figures in subscription reporting now exclude non-recurring products by default in the calculation itself. This prevents MRR and YRR totals from being accidentally overstated if someone removes the usual recurring filter in the report view.
Original PR description
While investigating a support ticket, we noticed that in subscription reports, recurring revenue values (MRR and YRR) are implicitly calculated for non-recurring products. This doesn't cause a direct problem when using the default search domains applied in Subscription > Reporting > Subscription > Pivot view, because a "Recurring" filter is pre-applied. But if the end user removes said filter, they might accidentally fudge the MRR and YRR numbers because the non-recurring products will contributed to the relevant grouping sums. We fix this by adding a CASE clause to explicitly ignore non-recurring products when calculating the report field for MRR and YRR , i.e. only consider `t.recurring_invoice = TRUE`. OPW-6315091 Forward-Port-Of: odoo/enterprise#121566
4 changes
Enhancements to existing features
This update prepares the Austrian accounting configuration for a VAT rate change effective July 1, 2026, reducing tax from 10% to 4.9% for certain food categories. It also updates the related chart of accounts and tax return mapping so businesses stay compliant and reporting remains accurate.
Original PR description
From first of July 2026, the VAT will change from 10% to 4.9% for some food categories. Adapt the taxes, the CoA and the tax return accordingly. task-6273259 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272321 Forward-Port-Of: odoo/odoo#268278
Resolved issues and error corrections
This change makes an automated French leave test more reliable by using a fallback time zone when the user’s time zone is not set. It prevents test failures in Odoo’s runbot checks without changing normal user behavior.
Original PR description
Currently the test test_holiday_in_week is failing in runbot tests This is due to the fact that during the tests the user tz in env is not set and hence it fails in the pytz library. Added a fallback to avoid the issue runbot issue opw-237623 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#248941
This update prevents PoS combo products from being incorrectly treated as items that must be registered with eTIMS in Kenya. As a result, customers can sell combos normally without unnecessary warnings or payment blocking.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5.…
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306 Forward-Port-Of: odoo/enterprise#121205 Forward-Port-Of: odoo/enterprise#119362
When an invoice is created for only part of a sale order, Odoo now links only the delivery notes that match the invoiced quantity. This avoids invoice XML files referencing extra delivery notes and keeps accounting records consistent.
Original PR description
### Issue: When invoicing partial quantities from a sale order, more DDTs than necessary are linked to the invoice Since `l10n_it_ddt_ids` is computed and not stored, the incorrect links persist…
### Issue: When invoicing partial quantities from a sale order, more DDTs than necessary are linked to the invoice Since `l10n_it_ddt_ids` is computed and not stored, the incorrect links persist until the remaining quantities are invoiced, at which point the extra DDTs are moved to the new invoice This creates inconsistencies in the generated XML, which references DDTs not actually covered by the invoice ### Cause: The quantity allocation loop only checked whether there was remaining `move_qty` to consume, but never checked whether the invoiced quantity (`inv[0]`) had already been fully consumed As a result, once all invoiced quantity was allocated, the loop kept iterating and linking additional DDTs from the sale order ### Steps to reproduce: - Install `l10n_it_stock_ddt` with demo data - Switch to the IT company - Create a Warehouse - Create a Product (Invoicing Policy: Delivered Quantities) - Create and confirm a Sale Order (qty: 5) for that product - Validate 3 partial deliveries of qty 1, creating a backorder each time - Create the invoice, set the quantity to 2 and confirm Before the fix, 3 DDTs were linked instead of 2 opw-6294035 Forward-Port-Of: odoo/odoo#270235
33 changes
Enhancements to existing features
Odoo now automatically emails companies when Stripe reports that their connected account may soon be restricted because required information or documents are missing. This helps businesses fix compliance issues before payments or account access are affected.
Original PR description
When a company tries to create a connected account, some official documentation need to be submitted to Stripe. Stripe takes care of the KYC steps and might restrict some account which don't meet the requirements. Odoo receives the details about the error and the date of the restriction. This task aims at sending automatic emails to the said companies to let them know that they need to fix the identified issues. task: 5441662 Forward-Port-Of: odoo/enterprise#107918
This update adjusts the AI website builder to match recent template changes in the main Odoo codebase. It helps ensure the feature continues to work correctly when users edit or build website content, without unexpected breakage from the underlying XML changes.
Original PR description
Adapt the XPath to the XML changes in community for the website.WebsiteBuilder template. task-6251151 Forward-Port-Of: odoo/enterprise#121655
The bank reconciliation screen now has a clearer, easier-to-use layout on mobile devices. Users can also see key statement details and the remaining balance at a glance, which helps them reconcile accounts with more context and less effort.
Original PR description
Current behavior before PR: On mobile devices, the bank reconciliation dialog relied on the base kanban view of account move line, which is difficult to handle and lacked contextual information about…
Current behavior before PR: On mobile devices, the bank reconciliation dialog relied on the base kanban view of account move line, which is difficult to handle and lacked contextual information about the statement being reconciled. Desired behavior after PR is merged: The bank reconciliation flow on mobile uses a dedicated kanban view with a simplified layout. An informational line is displayed above the main view, showing the statement date, reference, and remaining balance for better context. Changes implemented: - Added a mobile-specific kanban view for bank reconciliation dialog. - Displayed an information line above the kanban view with statement date, reference, and balance like desktop view for bank reconciliation dialog. - Moved 'onSelectionChanged' to 'BankRecSelectCreateDialog' and shared it through 'bankRecInfo', moved 'remainingAmountFormatted' into the state, and removed the duplicated getters from the list and kanban renderers. - Kept the existing desktop layout and behavior unchanged. - Added a HOOT test to check the mobile bank reconciliation dialog. task-5502469 Forward-Port-Of: odoo/enterprise#106565
This change prevents avoidable warning logs when the system checks whether certain attachments are multi-page documents. It mainly benefits integrations and automated processes that create URL-based attachments, by keeping logs cleaner and avoiding extra error handling.
Original PR description
Return None when datas is empty alongside the existing mimetype check. Avoids unnecessary exception handling leading to logspam for URL type attachments where binary data is unavailable. This issue is only reproducible programmaticaly as the mimetype is not available with url type attachment in Odoo. Thus, it's a problem that only impact third party integrations, EDI connectors or any workflow that creates ir.attachment records directly. opw-6010528 Forward-Port-Of: odoo/enterprise#116080 Forward-Port-Of: odoo/enterprise#113396
Resolved issues and error corrections
The bank reconciliation search dialog now displays full reference text instead of cutting it off. Date and balance information is aligned at the top, making entries easier to review and compare.
Original PR description
This commit will remove the text-truncate from the reference so that we have it full. Also removing the align item so that the date and balance are on top. no task id Forward-Port-Of: odoo/enterprise#121078 Forward-Port-Of: odoo/enterprise#120963
Automatic bank reconciliation rules now keep each statement line's original payment reference instead of replacing it with the account name. This makes reconciliation entries consistent with the manual Set Account flow and helps users identify transactions accurately.
Original PR description
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent…
### Issue: When creating an automatic reconciliation rule by assigning the same account to multiple bank statement lines, the rule incorrectly overrides the original payment reference of subsequent lines with the account name This creates an inconsistent user experience Using the "Set Account" button directly keeps the statement line payment reference as the journal item label However, clicking the automatically generated reconciliation model button replaces that reference with the account name Before the fix, clicking the automated rule button on a third matching line overrides its label with the account name instead of keeping its unique reference ### Cause: In `_create_reconciliation_rule`, when an automatic model is generated, the dictionary used to create the counterpart line explicitly set `label` to `rule_data['account'].name` When a reconciliation model line has a specific label defined, Odoo uses it to replace the statement line `payment_ref` on the generated counterpart move lines Removing this default value allows the system to fall back on the original payment reference ### Steps to reproduce: - Install `account_accountant` - Go to the Bank Reconciliation widget from the Accounting Dashboard - Create 2 statement lines without partners (e.g., Ref: "Test Ref 1" and "Test Ref 2") - Set the same account on both lines using Set Account - This automatically creates a Reconciliation Rule named after the account - Create a 3rd statement line with a matching reference (e.g., "Test Ref 3") - Click the newly available automatic reconciliation button for this line Before the fix, checking the generated entry label shows the account name instead of "Test Ref 3" To check unfold the details, click on the pencil icon of a line opw-6246833 Forward-Port-Of: odoo/enterprise#121850 Forward-Port-Of: odoo/enterprise#119133
The German SKR03 accounting template now uses the correct default accounts for cash discounts. This helps German companies avoid incorrect account mappings in financial reports and exports.
Original PR description
The default cash discount accounts referenced in the German skr03 template used the wrong account codes. The template has been updated with the right ones. task-4915939 opw-4909059 Forward-Port-Of: odoo/enterprise#121692 Forward-Port-Of: odoo/enterprise#121180
Opening a billing time target could fail for users with timesheet access but without employee access. The update adds the missing leave information needed by the page, so users can view billing targets without interruption.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` and `current_leave_id` field, change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value. Forward-Port-Of: odoo/enterprise#121888 Forward-Port-Of: odoo/enterprise#121571
This change ensures customer addresses in Field Service planning cards stay within the card instead of spilling past the edge when the address is long. It improves readability and keeps the kanban view visually consistent for users with customers that have detailed address lines.
Original PR description
Steps to reproduce: - 1. Open the Field Service planning view in kanban. 2. Make sure a shift's customer has a long address (long street lines). 3. Look at that shift's card in the kanban view. Issue: - The customer address overflows the card and is clipped at its right edge instead of staying within the card boundaries. Cause: - The customer is rendered with the `many2one` widget and `show_address`, which marks each address line `text-truncate`. Truncation only works inside a width-bounded container, but the field root `.o_field_many2one` is an inline-flex item with the default `min-width: auto`, so it grows to fit the longest address line instead of shrinking to the card. As a result, `text-truncate` never engages and the address spills past the card. Fix: - Add the `min-w-0` class to the partner field so the flex item shrinks to the available card width. task-6272209 Forward-Port-Of: odoo/enterprise#119248
The planning app no longer shows the shift role warning to users who cannot act on it. This reduces confusion for regular users while keeping the warning available to administrators who can assign roles and resolve the issue.
Original PR description
This commit hides the warning about a resource missing the shift's role from users without the "Planning > Administrator" access right, as only administrators can assign roles and act on the warning. task-6303545 Forward-Port-Of: odoo/enterprise#121447
Spanish companies can now open the Mod 349 tax return without the system crashing. The fix avoids a report check that assumed a different report layout, preventing an error when users access Tax Returns.
Original PR description
Steps to reproduce: - Install `Accounting` and `l10n_es` module - Switch to `Spain` company - Open `Tax Returns` Traceback: ```py File…
Steps to reproduce:
- Install `Accounting` and `l10n_es` module
- Switch to `Spain` company
- Open `Tax Returns`
Traceback:
```py
File "/data/build/enterprise/account_reports/models/account_return.py", line 2699, in _check_suite_common_ec_sales_list
engine_results = custom_handler._report_engine_ec_sales_report(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/data/build/enterprise/account_reports/models/account_sales_report.py", line 396, in _report_engine_ec_sales_report
return {next(iter(formulas_dict.values())): results}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
StopIteration
```
Cause:
In the method `_check_suite_common_ec_sales_list`, `formulas_dict` is built by taking `line_ids[0].expression_ids.grouped('formula')`. This assumes the first report line always has expressions defined, which holds true for standard EC Sales List reports.
However, Mod 349 has a different report structure where the first line is a "Summary" line with no expressions, resulting in `formulas_dict` being an empty dict. When `_report_engine_ec_sales_report` then calls
`next(iter(formulas_dict.values()))` to retrieve the formula key, it raises a `StopIteration` error, causing a crash whenever a Spanish company opens the tax return report.
Solution:
Override `_check_suite_common_ec_sales_list` for Mod 349 to only run the basic checks, bypassing the engine call that caused the crash. All other return types still go through the generic suite via `super()`.
opw-6222938
sentry-7513259974
Forward-Port-Of: odoo/enterprise#117850This change fixes an issue in Mexican electronic invoicing where invoices with many related document links could fail to save or search correctly. It improves reliability for complex cancellation cases while keeping lookups fast.
Original PR description
The field `l10n_mx_edi_cfdi_origin` can contain a large number of associated UUIDs, especially in complex cancellation scenarios. The default B-tree index fails when this field exceeds 2704 bytes, which occurs after approximately 20 UUIDs. By switching to a trigram index, we avoid the entry size limit of PostgreSQL's B-tree nodes. This ensures that invoices with many related documents can be processed while maintaining efficient search performance for partial matches on this field. **Video before the fix:** https://youtu.be/24u0HbxwIH8 **Video after the fix:** https://youtu.be/sUelv1HZMvI Forward-Port-Of: odoo/enterprise#118868
This fix ensures the Tickets Closed number matches the tickets that should be counted, excluding tickets closed today. It makes the helpdesk dashboard and related filters more accurate for users reviewing recent activity.
Original PR description
Before: The Tickets Closed number matches the actual tickets when clicking on it. It shows the tickets closed today, which should be excluded. After: Change the domain of the `ticket_closed` to be able to exclude tickets that are closed today --- task-6234330 Forward-Port-Of: odoo/enterprise#120454
This update prevents Italian fiscal printers from failing when product, payment method, or POS names include unsupported space-like characters. It replaces those characters with standard spaces before sending the print command, helping receipts print correctly and avoiding interrupted sales.
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#121538 Forward-Port-Of: odoo/enterprise#120169
Subscription reports now ignore non-recurring products when calculating monthly and yearly recurring revenue. This prevents inflated figures if users remove the built-in recurring filter in the report view.
Original PR description
While investigating a support ticket, we noticed that in subscription reports, recurring revenue values (MRR and YRR) are implicitly calculated for non-recurring products. This doesn't cause a direct problem when using the default search domains applied in Subscription > Reporting > Subscription > Pivot view, because a "Recurring" filter is pre-applied. But if the end user removes said filter, they might accidentally fudge the MRR and YRR numbers because the non-recurring products will contributed to the relevant grouping sums. We fix this by adding a CASE clause to explicitly ignore non-recurring products when calculating the report field for MRR and YRR , i.e. only consider `t.recurring_invoice = TRUE`. OPW-6315091 Forward-Port-Of: odoo/enterprise#121566
This fix ensures barcode scans can correctly find lots even when the lot number contains special characters or begins with the GS1 code used to identify lots. As a result, stock operations like internal transfers will no longer fail to recognize the lot and will validate properly after scanning.
Original PR description
When we scan a gs1 barcode that has in his lot a special character and start with 10, odoo will not be able to retrieve it from the db. **Steps to reproduce** * In settings activate: - Lots & Serial…
When we scan a gs1 barcode that has in his lot a special character and start with 10, odoo will not be able to retrieve it from the db. **Steps to reproduce** * In settings activate: - Lots & Serial Numbers - Units of Measure & Packagings - Storage Locations - Barcode Scanner : GS1 nomenclature * Create a Product tracked by lot with - barcode: 00001234567895 * Add on hand quantity: - 100 kg in lot : 10002002303-4 - 100 kg in lot : 11002002303-4 * Go to barcode>Operation>Internal Transfer>New * Scan 02000012345678951010002002303-4#3100000100 meaning: - 02 following 14 characters are the product barcode - 10 following characters are the lot number - "#" separator - 3100: means the units are kilograms, - 00100 means 100 units. -> if you check with the edit button the lot was not found (if you click on validate it will trigger an UserError for missing lot) **Observation** When scanning the GS1 barcode it will call onBarcodeSubmitted->onBarcodeScanned where we will execute processBarcode: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/components/main.js#L387 Where we will deconstruct the barcode into his component en retrieve from the db the relevant data: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/models/barcode_model.js#L709-L717 - First the barcode is parsed, identifiers are erased and each section is separated, the variable with our lot number only has the lot number in it, the identifier (10) is not included, BarcodeObject.forBarcode(bc) -> new BarcodeObject -> parser.parse_barcode: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/barcode_object.js#L14 - Check if the data is in the cache, if not, set it to retrieve after - Retrieve missing data getMissingRecords : https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/static/src/lazy_barcode_cache.js#L349 From here we will get a call to get_specific_barcode_data for each element: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L176 In the case of the stock.lot since it has a symbol and it's not only digit it will skip the gs1 nomenclature domain converter (it will not become 'ilike' and stay with 'in'): https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L182-L197 We will do the search: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/controllers/stock_barcode.py#L205 during which we will retrieve specific query from the stock.lot module : https://github.com/odoo/odoo/blob/8d14665af5acf1bd391d05a5048dc701986e8b15/odoo/orm/models.py#L1408 Where, since it's a GS1 nomenclature, we will preprocess the agrs: https://github.com/odoo/enterprise/blob/8030b105d3fce1eef9b8965a2bfc37195f71723c/stock_barcode/models/stock_lot.py#L14 -> Since our barcode start with a 10, it will erase it, which lead to a miss in the search. It will also avoid further searches since we avoid multiple search on the same elements (added in missingBarcodeKeyCache in getMissingRecords). https://github.com/odoo/enterprise/blob/c6d18a7a92092ffdf96f4569a70e95bdc276441c/stock_barcode/static/src/lazy_barcode_cache.js#L294-L298 opw-6207120 Forward-Port-Of: odoo/enterprise#118828
This change fixes access rights for completed signed documents so they stay consistent after completion. It helps ensure the right people can view or handle finalized documents without unexpected permission issues.
Original PR description
Forward-Port-Of: odoo/enterprise#121576
This change fixes an issue where ticket status labels could appear differently depending on the view. After the update, list and form views now show the same renamed status labels as the kanban view, so users see consistent wording everywhere.
Original PR description
Steps to reproduce: ------------------------ 1. Install Helpdesk 2. Go to All Tickets and check the kanban state selection value 3. Go to Settings > Field Selection and search for kanban_state in…
Steps to reproduce:
------------------------
1. Install Helpdesk
2. Go to All Tickets and check the kanban state selection value
3. Go to Settings > Field Selection and search for kanban_state in `helpdesk.ticket` model
4. Change one of the state selection values (e.g., "Ready" to "Testing Ready")
5. Go back and check the state selection value in list and form views
Current behavior:
-----------------------
Kanban view correctly shows the updated label (e.g., "Testing Ready"),
but list and form views still display the old default value (e.g., "Ready").
Root cause:
---------------
The [state_selection](https://github.com/odoo/odoo/blob/c09cefdb0ed68b1b7367b77b18a5ee5d66c94900/addons/web/static/src/views/fields/state_selection/state_selection_field.js#L57-L65) widget uses `legend_${state}` field values when available.
Since list and form views included these legend fields, the widget resolved labels from them
instead of the actual selection values, causing inconsistent display.
Fix:
-----
Remove `legend_normal`, `legend_blocked`, and `legend_done` fields from the list and form views,
So the widget falls back to the real selection labels, consistent with how the kanban view behaves.
Reference commit: https://github.com/odoo/enterprise/commit/65f3b88254e3a66e2c5dcb5142d30f6b1996d999
opw-6238765
Forward-Port-Of: odoo/enterprise#119707This update corrects how rental prices are shown on the website product configurator. The price now appears in the expected format with a slash between the amount and the rental period, making it clearer for customers.
Original PR description
Steps to produce: --- - Install the `Rental and eCommerce `modules. - Create a rental product and configure a rental price for it. - Add an optional product from the Sales tab. - Publish the product…
Steps to produce: --- - Install the `Rental and eCommerce `modules. - Create a rental product and configure a rental price for it. - Add an optional product from the Sales tab. - Publish the product on the website. - Open the product page on the website and click` Add to Cart`. Issue: --- - In the product configurator, the rental price is displayed without the `/` separator between the price and the rental duration period. Cause: --- - The string used to generate the rental duration label does not include the `/` separator. Fix: --- - Add the missing `/` separator to the rental duration label so that rental prices are displayed correctly. Before: --- <img width="974" height="185" alt="image" src="https://github.com/user-attachments/assets/64a88a60-bcc0-4657-97fd-584da57d0aff" /> After: --- <img width="967" height="188" alt="image" src="https://github.com/user-attachments/assets/b4d50019-1db4-4817-a8ce-446cc3c55df4" /> opw-6293015 Forward-Port-Of: odoo/enterprise#121637 Forward-Port-Of: odoo/enterprise#120223
Tax unit members who are not part of the main company can now see tax return checks as well as tax returns. This helps them identify and correct issues that would otherwise block their tax filings.
Original PR description
Before this commit: Tax Unit Members other than main company have read access to tax returns but don't have read access to tax return checks. After this commit: Tax Unit members other than main company are given read access to tax return checks also, so they can fix checks failing because of them. task-5951364 Forward-Port-Of: odoo/enterprise#113118
This change fixes a test in the SEPA direct debit flow that could try to confirm a payment twice under certain module setups. It helps prevent test failures and keeps the payment process checks reliable across different configurations.
Original PR description
The `test_expiry` test creates a payment via the `pay_with_mandate` method. Depending on eg. the installed modules, the resulting payment ends up either `paid` or `reconciled`. Afterwards, the test tries to validate the payment, which requires that it not be in the `reconciled` state. This causes an error linked below. This PR adds a condition to ensure the payment is in the `paid` state before attempting to validate it. Error: https://runbot.odoo.com/odoo/error/240557 Forward-Port-Of: odoo/enterprise#112224
This change makes the French VAT submission use the correct form version based on the reporting period. It prevents reimbursement and VAT returns from being rejected by the tax authority when the campaign year changes.
Original PR description
The 3519 reimbursement form is rejected by the DGFiP with "Le millesime 25 du formulaire 3519 est inconnu dans la teleprocedure TVA". The 3310CA3 return is still accepted, because its layout is unchanged year-on-year, which hides the problem, but it is sent with a millesime that no longer matches the campaign. The millesime is the form-version year. The EDI-TVA 2026 campaign opened on 2026-02-09. last update: https://github.com/odoo/enterprise/pull/92542 opw-6275695 Forward-Port-Of: odoo/enterprise#120969 Forward-Port-Of: odoo/enterprise#120759
This update prevents overtime records from overlapping when an employee’s attendance spans multiple days. It fixes an error that could appear at day boundaries, making overtime processing more reliable for employees with cross-day shifts.
Original PR description
**Problem:** When an attendance has overtimes across multiple days, those overtimes can overlap when calculating their intervals. There will always be rounding errors since only the durations are…
**Problem:** When an attendance has overtimes across multiple days, those overtimes can overlap when calculating their intervals. There will always be rounding errors since only the durations are saved to 3 decimals, but this is normally fine since the durations are accumulated when calculating the next interval. However, on a day boundary in the employee timezone, the end of the interval is forced to the end of day, which incidentally removes the rounding error. This causes the overlap when calculating the next interval since its start will be based on the rounded duration, not the actual end of day. **Steps to Reproduce:** - Configure an overtime rule where >8 hours is considered overtime, and a second rule applies to non-working days - Set Overtime Rule on employee "Anita Oliver" - Set employee work entry source to "Attendances" - Create an attendance that exceeds 8 hours in a day and crosses into a non-working day and creates enough of a rounding error (see unit test) -> Traceback error: `ValueError: Expected singleton: hr.attendance.overtime.line(1, 2)` **Solution:** Add an additional check to ensure the overtime cannot start on the previous day. opw-6067969 Forward-Port-Of: odoo/enterprise#119672 Forward-Port-Of: odoo/enterprise#118570
This change prevents the Czech localization from taking over records it should not manage when the chart of accounts is reloaded. It helps keep existing accounting data stable during updates and avoids unintended changes during maintenance.
Original PR description
It is the burden of the CoA framework to check for that. See community commit for more information. Forward-Port-Of: odoo/enterprise#121783 Forward-Port-Of: odoo/enterprise#121643
The salary configurator no longer crashes when the company car option is enabled without a car model selected. This makes the Belgian contract salary setup work correctly even when no demo data is installed.
Original PR description
## Steps to Reproduce: 1. Install `l10n_be_hr_contract_salary` without demo data. 2. Create a Belgian company and switch to it. 3. Create an employee. 4. Create a contract for the employee. 5. Click Generate Offer and open the Salary Configurator. 6. Enable the 'Company Car (To order)' option. ## Error: `AttributeError: 'NoneType' object has no attribute 'split'` ## Cause: When the salary configurator is used without demo data, no car model is selected. The method assumes that select_wishlist_car_total_depreciated_cost always contains a value and directly calls split() on it, resulting in an error, when the field is None. ## Fix: This commit checks that both the company car option is enabled and a car model has been selected before trying to extract the model ID. sentry-7554712017 Forward-Port-Of: odoo/enterprise#121650 Forward-Port-Of: odoo/enterprise#121138
This change makes the POS tour wait until the order status update is fully processed before moving on. It also switches the screen to the Paid filter so the order is found in the correct list, preventing intermittent test failures.
Original PR description
The tour `test_product_level_discount` was failing intermittently because the order status update request was not fully processed before the nextstep executed. As a result, the tour searched for the order in the wrong ticket list. This commit adds a proper wait for the backend request after updating the order status and applies the Paid filter on the ticket screen to ensure the tour searches in the correct order list. Runbot Error: [241140](https://runbot.odoo.com/odoo/runbot.build.error/241140) Forward-Port-Of: odoo/enterprise#109371
This change prevents the system from creating duplicate draft transactions when the import cron runs. It restores the previous behavior for repeated files so businesses avoid seeing the same draft move created more than once.
Original PR description
Since this commit: https://github.com/odoo/enterprise/commit/a0c9e9b5c0ed8135d77c343c819c1fa918356794 users are experiencing some duplicate draft move when the cron is running. It's because we don't skip the files when it already exist, we now add a number of imported count. This commit will revert this change to avoid the problem, and we will contact codabox to find a better way to deal with files imported the same month. task-6299508 Forward-Port-Of: odoo/enterprise#121472
The Spanish Mod 349 report was incorrectly dropping invoices that had been paid during the reporting period. This fix ensures only the intended credit note adjustments are excluded, so the report now stays accurate for businesses with paid invoices.
Original PR description
The mod349 report engine has been refactored to use tax tags (commit : 5f36778288a1b60245acec74677421666448351f). To avoid redundancies, the query used to get the invoice lines to include is designed to remove the amounts that have been reconciled with a credit note during the selected period. However, the current query removes the lines from any invoice that is reconciled with a move created in the period. As a result, invoices that have been paid in the period are also removed from the report. opw-6250491 Forward-Port-Of: odoo/enterprise#119551
A formatting issue prevented Mexico’s SW cancellation requests from sending the certificate in the expected encoded form. This fix restores the correct certificate format so cancellations can be processed reliably again.
Original PR description
Issue: https://drive.google.com/file/d/1-57iHrMoBo79EbUaWuwkJut_7FfyzeLY/view
`_sw_cancel` sent `pem_certificate.decode('UTF-8')` as `b64Cer`, which used to work because `fields.Binary` returned base64-encoded bytes. Since binary fields now return a `BinaryValue`, `.decode()` returns the raw PEM content instead of base64, breaking the SW cancel API call.
Use `.to_base64() " to properly base64-encode the certificate, matching the pattern already used for `b64Key " and in `_sw_sign ".
related change for binary fields: [41fe2eb](https://github.com/odoo/odoo/commit/41fe2ebdb9cc)
task-6319057
Forward-Port-Of: odoo/enterprise#121579This update corrects how Philippine tax reports identify invoice lines when taxes are grouped. It ensures lines are included under the right tax tag even when the relevant tag belongs to a child tax inside a group, so reports are more accurate and complete.
Original PR description
When using group taxes, the base invoice lines only store the parent tax in the `account_move_line_account_tax_rel` table. Because of this, if a child tax within the group contains a specific tax report tag, the generic report query would previously fail to pick up those base lines. This commit updates the SQL join conditions in `l10n_ph_generic_report.py` to also match `account_tax.id` against the child taxes of the linked parent tax using the `account_tax_filiation_rel` table. This ensures that base lines are correctly reported under the tags of their respective child taxes. Task-6278098 Forward-Port-Of: odoo/enterprise#121876 Forward-Port-Of: odoo/enterprise#121596
Currently, the sia_code field on res.company lacks length validation. For Italian Ri.Ba (CBI) exports, this field MUST be exactly 5 characters. If a user enters more (e.g., during initial setup), the Batch Payment validation (specifically the XML file generation) crashes with a traceback. Steps to Reproduce: - Set Company SIA Code to 6+ characters - Create multiple payments with Ri.Ba. method - Create a Ri.Ba Batch Payment - Click 'Validate' Ticket [link](https://www.odoo.com/odoo/proj
Original PR description
Currently, the sia_code field on res.company lacks length validation. For Italian Ri.Ba (CBI) exports, this field MUST be exactly 5 characters. If a user enters more (e.g., during initial setup), the Batch Payment validation (specifically the XML file generation) crashes with a traceback. Steps to Reproduce: - Set Company SIA Code to 6+ characters - Create multiple payments with Ri.Ba. method - Create a Ri.Ba Batch Payment - Click 'Validate' Ticket [link](https://www.odoo.com/odoo/project.task/6031062) opw-6031062 Forward-Port-Of: odoo/enterprise#121610
The aim of this commit is to allow the databases_user to synchronize their databases. Context: The commit https://github.com/odoo/odoo/commit/846eb51a02baaf2e4f6e6780f8d0ceb23322c38b introduced a change of behavior in stable that performs some more check on access rights. Before this commit: The checks introduced by the commit resulted in an access error. There wasn't any groups on the action itself resulting in a check of the access right "write" on the model. As the model is `project.
Original PR description
The aim of this commit is to allow the databases_user to synchronize their databases. Context: The commit https://github.com/odoo/odoo/commit/846eb51a02baaf2e4f6e6780f8d0ceb23322c38b introduced a change of behavior in stable that performs some more check on access rights. Before this commit: The checks introduced by the commit resulted in an access error. There wasn't any groups on the action itself resulting in a check of the access right "write" on the model. As the model is `project.project` and a databases_user might not be granted write access on the project itself, it resulted in an access error. After this commit: The flow continues smoothly. As the action has now a group set on it, this is checked first and match the proper access right. opw-6329058 Forward-Port-Of: odoo/enterprise#121589
Selecting a second model through the Action option's "More models" crashed because the current form model was dropped from the models cache while the new model was being applied. This commit keeps both the current form model and the model being applied in the cache. Steps to reproduce: - Add a form snippet - Click on the form - In the `Action` option, select `More models` - Select one model - Open `More models` again and select another model - Traceback appears: `TypeError: Cannot re
Original PR description
Selecting a second model through the Action option's "More models" crashed because the current form model was dropped from the models cache while the new model was being applied. This commit keeps both the current form model and the model being applied in the cache. Steps to reproduce: - Add a form snippet - Click on the form - In the `Action` option, select `More models` - Select one model - Open `More models` again and select another model - Traceback appears: `TypeError: Cannot read properties of undefined (reading 'website_form_key')` task-6321878 Forward-Port-Of: odoo/enterprise#121492
4 changes
Enhancements to existing features
This update adds two new delivery provider options: Food Zapp for the UAE and Enqueue for Saudi Arabia. It helps businesses in these markets connect their point of sale delivery setup to more local provider choices.
Original PR description
In this commit: - We are introducing two new providers, FoodZapp and Enqueue, for the UAE and KSA, respectively. Task-6263190,6263310
Resolved issues and error corrections
The Shopee connector has been updated to handle buyer identifiers that are larger than the original limit. This prevents errors when creating or matching customer contacts for affected Shopee accounts.
Original PR description
When the Shopee connector was introduced, Shopee documented `buyer_user_id` as an int32. We therefore store it in an `Integer` field, which maps to a PostgreSQL int32 column. However, feedback showed that Shopee can send ids exceeding the int32 bounds, leading to a traceback when creating new contacts. Shopee has since updated their documentation to confirm the field is actually an int64. Since we are in stable and cannot change the column type, this commit falls back to the `ref` field of the `res.partner` model to store and match Shopee contacts whose identifier doesn't fit within an int32. opw-6325948 See also: - master: https://github.com/odoo/enterprise/pull/121507 - upgrade: https://github.com/odoo/upgrade/pull/10578 Forward-Port-Of: odoo/enterprise#121498
This update ensures the Italian Ri.Ba. company code is exactly 5 characters, as required for CBI exports. It prevents batch payment validation from failing with an error when the code is too long, helping users complete payments without interruptions.
Original PR description
Currently, the sia_code field on res.company lacks length validation. For Italian Ri.Ba (CBI) exports, this field MUST be exactly 5 characters. If a user enters more (e.g., during initial setup), the Batch Payment validation (specifically the XML file generation) crashes with a traceback. Steps to Reproduce: - Set Company SIA Code to 6+ characters - Create multiple payments with Ri.Ba. method - Create a Ri.Ba Batch Payment - Click 'Validate' Ticket [link](https://www.odoo.com/odoo/project.task/6031062) opw-6031062 Forward-Port-Of: odoo/enterprise#121610
This update fixes an error that could appear when opening a billing target in Timesheets under certain access settings. It ensures the needed employee availability information is available, so users can view billing targets without the page breaking.
Original PR description
Prerequisites to reproduce: - Enable `Billing Rate Indicators` in timesheets. - Change timesheet access of user to `User: all timesheets` - Remove Employee access Steps to Reproduce: - In Timesheets app, from configuration go to `Billing Time Targets` - Click on view button on any row Issue: - A traceback breaking the flow. Reason: - We use `hr_presence_status` widget which requires `leave_date_to` change made from odoo/odoo@0496ed1 and https://github.com/odoo/odoo/commit/4b5089694436aa00254666e10cd2106b21adfe2b - Thus unavailability of field causing the traceback. Fix: - Add a related field for leave_date_to from which we get the value. Forward-Port-Of: odoo/enterprise#121571
7 changes
Enhancements to existing features
The POS fiscal integration now sends buyer address details only when they are actually available. This avoids transmitting placeholder values like “N/A”, which makes the submitted data cleaner and more accurate for Fiskaly.
Original PR description
In this commit: ------------------- - Buyer address fields are optional and should only be sent to Fiskaly when they are actually available. - Avoid sending placeholder values like "N/A". If the data is not present, the fields should simply be omitted from the request. task: 6113133
Backorder creation during receipt validation has been optimized so it can handle very large operations much faster. This reduces the risk of timeouts and database memory errors, helping busy warehouses complete receipts more reliably.
Original PR description
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of…
## The Problem Validating receipts with a large number of operations by creating a backorder was timing out due to $O(N*M)$ filtering inside `_get_qty_received_without_self`, where N is the number of moves in the picking, and M is the number of moves being processed for valuation. This happened while computing price units for moves one by one: each move filtered all picking moves to find the ones with the same `product_id`. Another issue was a PostgreSQL `"memory exhausted"` error caused by generating a large number of OR'ed conditions, equal to the number of processed moves. ## The Solution The massive filtering was fixed by filtering moves of the `purchase_line` instead of the `picking`, which is typically associated with only a few moves. This is still correct as the loop just after already ignores moves that don't have the same `purchase_line_id` of `self` anyways. The PostgreSQL error was fixed by grouping moves by `location_dest_id` and generating one condition per location using an `in` clause, which is typically much smaller than generating one condition per move. ## Benchmark Benchmark on a customer database, validating a receipt with 10k+ operations by creating a backorder: ```text Time: timeout -> 6 min ``` OPW-6272667
This update brings back automated flow tests for the French Point of Sale payment reporting and invoicing process. It helps ensure the merged e-reporting and e-invoicing logic continues to work as expected and reduces the risk of regressions.
Original PR description
During the merge of l10n_fr_pdp e-reporting and e-invoicing, some tests had to be removed. Task-6296356
Resolved issues and error corrections
This change fixes the XML produced for Danish eInvoices when a line has both a tax and a discount. The invoice file now includes the missing tax classification details, so it passes Nemhandel validation and can be sent without errors.
Original PR description
### Steps to Reproduce 1. Activate l10n_dk 2. Have a Danish customer contact where the eInvoice format is OIOUBL 2.1 3. Create an invoice with them as the partner and make sure that the line has a…
### Steps to Reproduce 1. Activate l10n_dk 2. Have a Danish customer contact where the eInvoice format is OIOUBL 2.1 3. Create an invoice with them as the partner and make sure that the line has a tax and a discount 4. Download the XML and try to validate ### Description of the issue/feature this PR addresses: **Issue:** When sending customer invoices with discounts on lines with the OIOUBL 2.1 format, the generated XML fails official Nemhandel validation. The schematron rejects the file because line-level allowance blocks do not declare their tax classifications. Specifically, this violates mandatory compliance rule [F-LIB226], which says that one `TaxCategory` class must be present inside every `cac:AllowanceCharge` block on a line item. **Solution:** By using the target dictionary array after the base framework is generated, it gets the line's tax information using native grouping functions. It then injects the `cac:TaxCategory` sub-block directly into each array item mapping. ### Current behavior before PR: When a product line includes a discount, Odoo outputs a standard line-level `cac:AllowanceCharge` block. It does not include the necessary tax information. This incomplete XML causes Nemhandel to throw an error. ### Desired behavior after PR is merged: Every line-level discount allowance generated for a Danish invoice will include the relevant tax classification metadata downstream into the XML. This will ensure that it is accepted by Nemhandel. opw-6226549 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix ensures that key records created when using Marketing Automation templates, such as the confirmed contacts list and its related action, are kept during system upgrades. As a result, users will no longer see these template-generated items disappear after upgrading the module.
Original PR description
When a user chooses the "Double Opt-in" template (or others using `_create_records_with_xml_ids`), the system creates records like the "Confirmed contacts" list and a server action. It also adds an…
When a user chooses the "Double Opt-in" template (or others using `_create_records_with_xml_ids`), the system creates records like the "Confirmed contacts" list and a server action. It also adds an `ir.model.data` entry for them under the module, but sets `noupdate=False`. The problem is that during a module upgrade, Odoo's cleanup process (`_process_end`) deletes any record marked `noupdate=False` if it wasn't "reloaded" from a file. Since these records are created manually in the code and aren't in any XML file, they never get reloaded, so Odoo just deletes them and the records they point to. By setting `noupdate=True` when these rows are created, we tell the system to leave them alone during upgrades. Since these only exist at runtime and don't have a data file, we don't need to worry about them being updated later anyway. The helper was added in https://github.com/odoo/enterprise/commit/fd98660e352512e0b74d91958707687978154833. Steps to reproduce: 1. Install Marketing Automation 2. Go to Campaigns > New and pick the "Double Opt-in" template, then save 3. Confirm the "Confirmed contacts" mailing list and server action exist 4. Go to Apps and Upgrade Marketing Automation 5. Try to find the mailing list and server action again => They disappear after the upgrade. Ticket [link](https://www.odoo.com/odoo/project.task/6140191) opw-6140191
When users scan a product in the Barcode app, the system now better preserves the product owner on the delivery line when this information is available. This helps ensure existing stock is used correctly, avoiding unnecessary creation of new stock entries and reducing inventory inconsistencies.
Original PR description
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations >…
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations > Delivery Orders > New - Scan your product and validate #### > The owner was not set on the stock move line so that a new quant was created and updated in stock rather than using the available unit. ### Cause of the issue: The mechanism of prefilling an owner or a package in the barcode app is currently gate-kept behind the existence of a lot name: https://github.com/odoo/enterprise/blob/0be4f71de3420fb9b72fd4e70d48c6cbbbc0ecb4/stock_barcode/static/src/models/barcode_model.js#L1382-L1407 However, the option also make sense for none tracked products. ### Note: Performing the flow form the backend and adding quantity will generate the move line by setting the owner if possible since the quantity of a move is set via the back end, move lines are generated by looking at the existing quant data's: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2364 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2328-L2330 Setting the same owner on the new move line as on the quant we are going to reserve: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2337 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L1715 Additional subtelties appearing when prefilling for non tracked product: 1. Currently the available quantity is not taken into account to determine if the the value provided to the prefilled is actually relevant, in particular if there is a quant with an available quantity of 0, it will be used as a valid value to prefill and it will parasit the prefill that could be done by other quants. 2. The location source used to determine the quants taken into account is not set on the first scan since the scan is performed without any existing line: https://github.com/odoo/enterprise/blob/4f0d25f9fe4ca8ff1b0ecd7900899a2a246ba888/stock_barcode/static/src/models/barcode_model.js#L1387 > This was not problematic with respect to tracked product since the product needs to be scanned prior to the lot, hence there is always a current line when the the lot is scanned. opw-6050657
This update fixes the website cookie bar layout so its buttons and links keep the right spacing when a layout is selected. It also prevents popup elements from being inserted inside other popups, avoiding confusing editing behavior on the website.
Original PR description
Steps to reproduce: - Enable the cookies bar in the website settings. - Go to the website and enter edit mode. - Open the cookies bar from the invisible elements panel. - Open the snippet dialog. => Popup snippets are still visible even though they cannot be dropped inside another popup. Before this commit, popup snippets could still use dropzones located inside another popup in some cases, such as cookie bars or newsletter popups. After this commit, when the dragged snippet is a popup, dropzones inside an existing popup are filtered out, so nested popups cannot be inserted. task-6251151