Daily updates from Odoo
Wednesday, July 1, 2026
250 changes
40 changes
New functionality added to Odoo
This update adds two new delivery providers to the Point of Sale integration: Food Zapp for the UAE and Enqueue for Saudi Arabia. It expands the available local delivery options for businesses operating in those markets.
Original PR description
In this commit: - We are introducing two new providers, FoodZapp and Enqueue, for the UAE and KSA, respectively. Task-6263190,6263310 Forward-Port-Of: odoo/enterprise#122001 Forward-Port-Of: odoo/enterprise#121461
Enhancements to existing features
The Inventory at Date wizard now opens the full stock report interface instead of a basic product list. This gives users the same search tools, action buttons, and stock details they already have when viewing current inventory, making past-date stock checks easier and more consistent.
Original PR description
## Summary Minimal alternative: make the "Inventory at Date" wizard open the same rich stock report view instead of the basic one. ### Problem The wizard opens `stock.view_stock_product_tree` (basic…
## Summary Minimal alternative: make the "Inventory at Date" wizard open the same rich stock report view instead of the basic one. ### Problem The wizard opens `stock.view_stock_product_tree` (basic product list) instead of `stock.product_product_stock_tree` (full stock report with action buttons and search panel). ### Solution Change the wizard's `open_at_date()` to use the stock report view and its associated search view. The wizard flow is preserved — this is purely a view swap. ### Changes - `stock_quantity_history.py`: Changed `tree_view_id` from `view_stock_product_tree` to `product_product_stock_tree`, added `search_view_id` for the stock report search view ### Alternative See #263507 for a more integrated approach that replaces the wizard entirely with a date picker in the search panel. [Task #6152466](https://www.odoo.com/odoo/rd-fun-logistics-966/6152466) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263509
This change lets operators adjust how long idle database connections stay open instead of using a fixed 10-minute limit. It helps systems with limited memory free unused connections sooner, improving stability and resource usage.
Original PR description
In memory-scarce environments, the default 10-minute idle timeout may keep too many backend connections alive. Allow operators to override it via the ODOO_DB_MAX_IDLE_TIMEOUT environment variable to evict idle connections more aggressively. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271785
Invoices sent outside KSeF now include a QR code and the KSeF reference number on the PDF. This helps recipients quickly verify and access the invoice information in line with Polish e-invoicing requirements.
Original PR description
While communicating outside KSeF, invoices must have a QR Code and their KSeF number displayed. QR Code content spec is available here: https://github.com/CIRFMF/ksef-api/blob/main/kody-qr.md task-6334901 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272480 Forward-Port-Of: odoo/odoo#271713
The stock move value can no longer be changed directly from the list view. Users must now use the Adjust Valuation process, which keeps valuation changes consistent and properly recorded with user and reason details.
Original PR description
### Description of the issue/feature this PR addresses: The stock move value was inline-editable in the moves list, which is misleading. Editing it directly behaves inconsistently across cost…
### Description of the issue/feature this PR addresses: The stock move value was inline-editable in the moves list, which is misleading. Editing it directly behaves inconsistently across cost methods: for FIFO products the edit updates the remaining value, but for AVCO products there is no mechanism to propagate it, so the change has no effect. The direct edit also bypasses the audited revaluation channel, the Adjust Valuation wizard (product.value), which records the user, date and justification. Disable direct modification by marking the field read-only by default, so manual revaluation always goes through Adjust Valuation. Internal valuation writes are unaffected. ### Current behavior before PR: The value field is editable in the stock move list view. <img width="1890" height="460" alt="image" src="https://github.com/user-attachments/assets/8ddc6495-4beb-4481-bdbf-2a44b70f3784" /> ### Desired behavior after PR is merged: The value field should not be editable. Users should use the Adjust Valuation wizard to ensure the operation is auditable. @qrtl QT6826 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267360
Resolved issues and error corrections
This fix prevents the AI assistant from retrying a task creation after an error, which could make it look like the same item was being created twice. It also checks that the required fields are present before showing the preview, making the confirmation flow clearer and more reliable.
Original PR description
This commit removes an issue where the LLM would retry on error when performing a creation which would give the impression that it created items twice. To do so, this commit now validates that the fields exists before calling the `create()` method, and before showing the preview to the user. Ensuring it avoids throwing an error after the message has been confirmed (resulting in the double preview). task-6229596 Forward-Port-Of: odoo/enterprise#118044
This change prevents the messaging system from crashing when it receives an unexpected value during subscription. It also makes message recovery more reliable after a database restore, so users are less likely to lose browser session continuity or hit errors in chat-like features.
Original PR description
`_prepare_subscribe_data()` crashes with a `TypeError` when last is not an integer, as the comparison with `_bus_last_id()` is not type safe. Since [1], this can happen naturally: when `_bus_last_id()` returns 0 after a DB restore, `broadcast()` drops the payload due to a falsy check. The tab then stores "undefined" in localStorage, which `parseInt` turns into `NaN`, which JSON encodes as `null`, which the server receives as `None`. Fix the falsy check in `broadcast()` so 0 is not dropped, use `|| 0` instead of `?? 0` when reading localStorage so corrupted values are recovered, and fallback any non integer last to 0 on the server. [1]: https://github.com/odoo/odoo/pull/270317
This update prevents a form error that could occur if a user quickly changed or deleted a field while the page was still loading. It also makes website form testing more reliable, reducing occasional failures in automated checks.
Original PR description
Before this commit, on slow networks users could trigger a traceback by quickly selecting a form field and deleting it. This happened because code executed from `FormFieldOption` `onWillStart` assumed the form field element still existed after awaiting asyncronous functions. This also caused the tour `test_website_form_conditional_required_checkboxes` to occasionally fail on runbot. This commit hardens the method `FormOptionPlugin.loadFieldOptionData` against DOM mutations that may happen while awaiting asyncronous code. In particular, `fieldEl` is now validated after every await. The code is also optimized such that syncronous code relying on the existance of the form field element is executed before the asyncronous one. Note that this change would not be necessary inside builder actions, but it is required because the code is also executed from `FormFieldOption` `onWillStart` and `onWillChangeProps`. runbot-940447
The website generator now matches product categories using unique IDs instead of category names. This prevents mix-ups when different categories share the same label, such as separate Accessories groups for men and women, and makes product setup more dependable.
Original PR description
Before we matched categories with products but names but this was less reliable in the case that we had multiple categories with the same name. e.g. Accessories (for men) and Accessories (for women). This new method allows for this and makes the matching more reliable.
Odoo now supports passkeys on Android devices by linking the website with the mobile app and accepting Android app sign-ins. This makes it easier for users to create and use passkeys from their Android phones while keeping the login flow compatible with Android’s requirements.
Original PR description
This commit adds a route for Digital Asset Links (`assetlinks.json`) that link the domain with the Android Mobile App. Also we adapt some functions authentication/registration so Odoo accept request…
This commit adds a route for Digital Asset Links (`assetlinks.json`) that link the domain with the Android Mobile App. Also we adapt some functions authentication/registration so Odoo accept request origin from the mobile App. The origin should be `android:apk-key-hash:BASE64(SHA256(APP_SIGNATURE))` Note: the `/.well-known/assetlinks.json` file should be serve on port HTTPS (443) without that the Android Digital Asset Links will fail. Url for debugging Digital Asset Links https://digitalassetlinks.googleapis.com/v1/assetlinks:check?source.web.site=https://MY-DOMAIN.local&relation=delegate_permission/common.get_login_creds&target.android_app.package_name=com.odoo.mobile&target.android_app.certificate.sha256_fingerprint=D6:73:20:02:CA:2D:01:C9:FD:FC:94:73:5A:D0:73:CF:2C:36:10:29:1F:4B:F7:5D:91:C2:1D:37:B2:18:E8:91 https://developers.google.com/digital-asset-links https://developer.android.com/identity/passkeys/create-passkeys https://developer.android.com/identity/credential-manager/prerequisites opw-6279212 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270551
This fix ensures subcontracted receipt quantities stay as entered, even after the scheduler runs. It prevents the system from reassigning these moves in the background, which could otherwise overwrite a user's manual quantity adjustment.
Original PR description
**Issue** Quantity on subcontracted receipts could be overridden after running the scheduler. **Steps to reproduce** - Create a subcontracting product - Create a PO for 10 units of that product - Go…
**Issue** Quantity on subcontracted receipts could be overridden after running the scheduler. **Steps to reproduce** - Create a subcontracting product - Create a PO for 10 units of that product - Go to receipt and open Subcontracting Productions' - Change the quantity to 5 - Enable debug mode. - Run Inventory/Operations/Procurement: run scheduler - Return to the receipt -> The receipt quantity is reset to 10 instead of remaining at 5. **Cause** Since the refactor introduced in commit: https://github.com/odoo/odoo/commit/fc66e2d4eb638f1486e69cd5920f02c787055da1, subcontracting receipt moves are no longer automatically picked when the production quantity is modified. In particular, this test case protects that behavior: https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/mrp_subcontracting/tests/test_subcontracting.py#L1629-L1631 When the scheduler runs: https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/stock/models/stock_rule.py#L731 it computes the moves to assign: https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/stock/models/stock_rule.py#L706-L710 However, subcontracting moves are still included in the assignment domain: https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/stock/models/stock_rule.py#L680-L688 https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/mrp/models/stock_rule.py#L127-L129 As a result, they are reassigned if they are not already picked: https://github.com/odoo/odoo/blob/f7fb0a941d6bac39b7057db36f57be079559912c/addons/stock/models/stock_move.py#L1931-L1937 opw-6229668 Forward-Port-Of: odoo/odoo#270837
This update stops popup snippets from being added inside other popups or restricted areas, which previously could cause errors and broken editing behavior. It also ensures the snippet list is rechecked after reloads so the available options stay correct for users.
Original PR description
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError:…
*: website, website_mass_mailing __Problem__ In some cases, popup snippets can be dropped inside another popup. This shouldn't be possible. Moreover, it produces the following error: `TypeError: Cannot read properties of undefined (reading 'after')`. This can happen in multiple scenarios: - After saving a custom snippet, the snippets are reloaded but `disableUndroppableSnippets` is not called again, although the snippets should be filtered again. - `NewsletterPopupPlugin` registers `.o_newsletter_popup` in the `so_snippet_addition_selector` resource, bypassing the more restrictive `dropzone_selector` of `PopupOptionPlugin`. - Popups are not disabled when the cookie bar is open because we don't take `excludeAncestor` into account in `DisableSnippetsPlugin`. __Fix__ - Trigger an event whenever the snippets are loaded and call `disableUndroppableSnippets` when it is. - Remove the redundant `NewsletterPopupPlugin`. - Filter `dropAreaEls` with `excludeAncestor` in `DisableSnippetsPlugin`. Forward-Port-Of: odoo/odoo#272273 Forward-Port-Of: odoo/odoo#269864
When a vendor bill is completed from a purchase order, some related invoice details can change. This update ensures the linked early payment discount lines are refreshed too, so totals and journal entries stay aligned with the final bill.
Original PR description
When a vendor bill is imported and auto-completed from a purchase order, then invoice lines, taxes, fiscal position, and payment terms can change. Existing EPD dynamic lines that lose their epd_key are skipped by sync and keep stale tax tags and amounts, causing mismatches between Invoice Lines and Journal Items. This commit makes EPD sync include keyless existing EPD lines so they are rewritten or removed during dynamic recomputation after PO auto-complete. Journal items remain consistent with the final invoice lines, taxes, and early discount configuration. Ticket [link](https://www.odoo.com/odoo/project.task/6047505) opw-6047505 Forward-Port-Of: odoo/odoo#272267 Forward-Port-Of: odoo/odoo#265539
Rapidly toggling a website popup could previously leave its visible state out of sync with the on-screen control. This fix makes the popup reliably finish its show/hide transition, which also prevents related issues when creating popups inside other popups.
Original PR description
__To reproduce__ 1. Drop a popup on the website. 2. Click twice rapidly on the popup show/hide toggle in the sidebar. => The popup visibility will be in an inconsistent state compared to the toggle's…
__To reproduce__ 1. Drop a popup on the website. 2. Click twice rapidly on the popup show/hide toggle in the sidebar. => The popup visibility will be in an inconsistent state compared to the toggle's eye icon. __Reason__ Bootstrap ignores any call to show/hide if the popup is still transitioning. __Fix__ - Set `_isTransitioning` to `false` to trick Bootstrap into firing the event regardless of its current state. - When hide/show are triggered in quick succession, the modal can enter an inconsistent state with `.show` class but `display: none` style (hide removes `.show` immediately, show restores it with `display: block`, then hide applies `display: none` after animation). Dispatching `transitionend` event before resetting `_isTransitioning` ensures Bootstrap completes its state transitions. __Note__ This commit also fixes `custom_popup_snippet`, which fails non-deterministically with the following error: `TypeError: Cannot read properties of undefined (reading 'after')` This error occurs when trying to add a popup inside another popup that never closes due to this bug. runbot-939039 Forward-Port-Of: odoo/odoo#269782
Table details now appear correctly in the order info screen for self-orders placed through QR menu or kiosk. This fixes the missing information so staff can more easily identify where an order belongs and handle service faster.
Original PR description
### **Issue** Self-orders created through the mobile QR menu or kiosk were not displaying table information in the Order Info section of the payment screen. ### **Root Cause** The Order Details…
### **Issue** Self-orders created through the mobile QR menu or kiosk were not displaying table information in the Order Info section of the payment screen. ### **Root Cause** The Order Details dialog relied on `order.getTable()` to retrieve table information. However, self-orders only store the table reference through `table_id`, which was not properly handled when rendering the dialog, resulting in missing table information. ### **Solution** This PR introduces the following changes: * Add a dedicated `getTableInfo()` helper in `pos_restaurant` to retrieve table information from the order. * Use `getTableInfo()` when building the Order Details dialog fields. * Allow self-order flows to provide table information through `table_id`, ensuring table details are displayed correctly. ### **Steps to Reproduce** 1. Enable the following options in POS Configuration: * QR Menu & Ordering * Service at Table * Online Payment 2. Open a self-order from the mobile QR menu 3. Select a table and complete the payment 4. Open the POS session 5. Open the paid self-order 6. Click the **Details** button on the right side ### **Video Reproduction** https://drive.google.com/file/d/138AoJCTF1HNlCGFgk9BRTb0UTai-uXX7/view?usp=sharing ### **Before** Table information was not displayed in the **Order Info** section for self-orders. ### **After** Table information is now correctly displayed for self-orders. opw-6179516 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271248 Forward-Port-Of: odoo/odoo#264046
This fix ensures users see the correct manufacturing orders when opening them from the statistics button. It prevents confusion by linking the overview to the actual orders that were manufactured.
Original PR description
* Following https://github.com/odoo/odoo/pull/261438 (forward-ported to 19.0 in #265323) we also need to show correct MOs when view from statsbutton Forward-Port-Of: odoo/odoo#265195 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#269201
This change prevents a crash that could happen when users add properties to a record that also uses computed fields or automatic updates. It ensures the property information is fully ready before the screen is shown, so the action works reliably instead of failing with an error.
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#272653 Forward-Port-Of: odoo/odoo#271082
This update prevents the Italian fiscal printer from getting stuck after the first receipt in Point of Sale. It removes a conflicting print path and keeps receipt printing aligned with the fiscal printer setup, so subsequent printer messages continue to work normally without needing a page refresh.
Original PR description
Module: l10n_it_pos Steps to reproduce: - In the POS settings, enable "Automatic Receipt Printing"; - Enable "ePos Printer" to make the "Skip Preview Screen" option appear; - Disable "Skip Preview…
Module: l10n_it_pos Steps to reproduce: - In the POS settings, enable "Automatic Receipt Printing"; - Enable "ePos Printer" to make the "Skip Preview Screen" option appear; - Disable "Skip Preview Screen"; - Disable "ePos Printer"; - Set up an Italian Fiscal Printer; - Open a POS session and process a first order. Issue: After the first receipt, no other messages (price display, receipt, open register) are sent to the fiscal printer. A page reload is required. Cause: When "Automatic Receipt Printing" is true but "Skip Preview Screen" is false, a race condition occurs. `afterOrderValidation` triggers a print job while simultaneously transitioning to the `ReceiptScreen`. When the `ReceiptScreen` mounts, it triggers a second fiscal print job before the first has resolved. This creates a deadlock in `toHtml` of `renderService`, permanently blocking the printer queue. Solution: Since the italian localisation sending the receipt to the fiscal printer is mandatory, the printing route is now tied to the "Skip Preview Screen" option. UI settings are adjusted to hide the redundant auto-print checkbox when an IT fiscal printer is configured. Community PR: https://github.com/odoo/odoo/pull/256932 [opw-5979212](https://www.odoo.com/odoo/project/49/tasks/5979212) Forward-Port-Of: odoo/enterprise#121779 Forward-Port-Of: odoo/enterprise#112654
The Planning search by skills now correctly shows employees who have the requested skill, even if they have no time slots in the selected period. This fixes a case where valid employees were being hidden from search results.
Original PR description
Issue: ---------------------------------------- Doing a search on skills, the employees with the skill but no slot in the time frame aren't shown. Steps to reproduce:…
Issue:
----------------------------------------
Doing a search on skills, the employees with the skill but no slot in the time frame aren't shown.
Steps to reproduce:
----------------------------------------
- Install `planning_hr_skills`
- Make sure an employee has the skill "English" and no slots
- Open Planning and type "English" in the search bar, click to search on Skills
- The employee does not show up
Cause:
----------------------------------------
Using the search view on skills, a filter on `resource_ids` is in the domain with a `OR`:
https://github.com/odoo/enterprise/blob/5d6d16aae43ffda1532cfa4b06fdcddd7e5b0fcc/planning_hr_skills/views/planning_slot_views.xml#L9
Then a new filter on `resource_ids` is added [here](https://github.com/odoo/enterprise/blob/5d6d16aae43ffda1532cfa4b06fdcddd7e5b0fcc/planning_hr_skills/models/planning_slot.py#L14-L43) to do the search on the skill names: `[('resource_ids', 'in', matching_resource_ids)]`.
The domain is then something like this:
`['&', ('resource_ids', 'in', matching_resource_ids), '|', ('resource_ids', '=', False), ('employee_skill_ids', 'ilike', 'English')]`.
Since fbf8b2ac67c71ca0abfc75df543069696bd2d29b the resulting domain passes through `filter_map_domain()`. `filter_map_domain()` will only keep the leaves on `resource_ids` and the default `AND` will be used between them resulting in:
`['&', ('resource_ids', 'in', matching_resource_ids), ('resource_ids', '=', False)]`
which fetches no resources.
So `_group_expand_resource_ids()` doesn't expand.
Solution:
----------------------------------------
Instead of adding the new leaf to retrieve the resources with the right skills, we replace the leaf on `employee_skill_ids`. This ensures the `OR` operations are kept by `filter_map_domain()`.
opw-6296755
Forward-Port-Of: odoo/enterprise#120669Code blocks in the editor will no longer open command menus or auto-convert text into lists. This avoids errors when users write code and keeps code content unchanged and reliable.
Original PR description
### Steps to reproduce: - Go to ToDo. - Create a code block using `/code`. - Place the cursor inside the code block. - Type `/table` and select the table command. - A traceback occurs. ### Purpose of this PR: - Commands and markdown shorthands should not be available inside code blocks. However, typing `/` inside a `<pre>` opened the command palette, allowing structural commands such as `/table` to be executed and causing a traceback. Similarly, markdown shorthands such as `* ` and `1.` were still active, unexpectedly transforming code content into lists. ### This PR fixes the issue by: - Disabling the command palette when the cursor is inside a `<pre>` element. - Disabling markdown shorthands inside `<pre>` elements by registering an `is_shorthand_available_predicates` predicate. task-6292231 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272271 Forward-Port-Of: odoo/odoo#269430
Imported supplier bill quantities are now kept at the right precision when linking them to purchase orders. This prevents small rounding errors that could slightly overstate invoiced quantities and amounts.
Original PR description
When importing an XML bill and linkin git to a purcahse order, the invoiced quantity may be computed incorrectly, due to a decimal precision mismatch. Steps to reproduce: - Import an XML bill having a line with quantity 1800.0 - Link to a purchase order with the same line Issue: The invoiced quantity will be computed with 1 cent difference (1800.01) Analysis: Because the system forced a decimal precision of 13 for 'Product Unit of Measure', quantity is imported as 1800.0000000000016. Later, when computing the invoiced quantity, the system round the quantity using 'UP' strategy, rounding the amount to 1800.01 opw-6194824 Forward-Port-Of: odoo/odoo#270916 Forward-Port-Of: odoo/odoo#266283
Employees with flexible schedules can now request a single day off on a public holiday when that holiday is meant to count in leave duration. This fixes a case where the request was incorrectly rejected, making behavior consistent with multi-day leave requests.
Original PR description
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is…
Currently, flexible employees can request a multi-day leave spanning a public holiday when the leave type includes public holidays in duration. However, requesting the public holiday date alone is rejected. ### **Steps to reproduce:** - Create a public holiday. - Create a time off type with "Public Holiday Included" enabled. - Select/create an employee with a flexible work schedule and its time zone must be same as admin. - Request a time off on the public holiday date only. ### **Observed Behavior:** The request is rejected because its duration is computed as 0 days. ### **Expected Behavior:** The request should be allowed and count as 1 day, consistent with the multi-day request behavior. ### **Root Cause:** At [1], a dedicated duration computation path is used for single-day leaves of flexible employees. This logic always retrieves overlapping public holidays and computes the leave duration based on the remaining intervals. As a result, a leave requested entirely on a public holiday is computed as 0 days, even when `include_public_holidays_in_duration` is enabled. [1]- https://github.com/odoo/odoo/blob/242f6d3cf7288853f163ac6986a3b7aa4279efaf/addons/hr_holidays/models/hr_leave.py#L436-L444 ### **Fix:** This commit ensures that the `include_public_holidays_in_duration` setting is taken into account when computing single-day leave durations for flexible employees **opw-6284768** Forward-Port-Of: odoo/odoo#272217 Forward-Port-Of: odoo/odoo#269743
This update fixes how net cost salary rules are calculated in the UAE and Saudi payroll localizations. It prevents contribution amounts from being dropped or counted the wrong way, so payroll totals stay accurate and consistent.
Original PR description
Steps: - Add a new salary category with the parent_id of company contribution (COMP) in AE - Create a dummy salary rule of that category - Compute a payslip and see the net cost unchanged Or - Create and compute a payslip in SA - Company contributions will be subtracted from each other Issue: - In AE localization, the issue with the rule was dropping salary rules that have a parent of company contribution category - In SA localization, the issue with the NETCOST was the aggregation of individual rules could include negative values which is not the intended flow. Solution: A standardized approach was adopted in both localizations in order to match the calculation of the NETCOST across. This approach will account for the categories with company contribution parent as well as the positive values for the individual salary rules. Forward-Port-Of: odoo/enterprise#120780 Forward-Port-Of: odoo/enterprise#115499
Vendor bills entered in a foreign currency are now matched correctly against GSTR-2B records. This fixes cases where bills were wrongly shown as partially matched even though the GST portal values were correct in INR, helping users reconcile returns without false errors.
Original PR description
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set…
**Steps to reproduce:** * Install the **l10n_in_reports** module. * Go to **Accounting → Configuration → Settings**, and enable **Multi-Currencies**. * Activate a foreign currency (e.g., USD) and set an exchange rate. * Create a new vendor bill for an Indian vendor, setting the currency to USD. * Add lines to the bill and apply IGST/GST taxes, then confirm the bill. * Go to **Accounting → Reporting → GST Return Period** and initiate GSTR-2B matching for the period corresponding to the bill (using a valid JSON payload where the amounts are correctly reported in INR). **Observed behavior:** * The vendor bill is incorrectly marked as "Partially matched" instead of "Fully matched", accompanied by an exception stating that the total amount as per GSTR-2B does not match. **Cause:** * The GSTR-2B data fetched from the GST portal always reports values in the company's base currency (INR). * The `match_bills` method was directly comparing the GSTR-2B INR amounts ( `bill_total` and `bill_taxable_value`) against the bill's `amount_total` and `amount_untaxed` fields. * Because these fields return values in the document's foreign currency (e.g., USD), the mismatch triggers an exception and flags the bill as partially matched. **Fix:** * Modified the matching logic to compare GSTR-2B values against `abs(amount_total_signed)` and `abs(amount_untaxed_signed)`. * This ensures that the amounts evaluated during reconciliation are always correctly converted and compared in the company's base currency (INR). opw-6311097 Forward-Port-Of: odoo/enterprise#121837 Forward-Port-Of: odoo/enterprise#120967
This change prevents a website error that could happen when adding a dynamic product block to a page. It makes the ribbon assignment logic skip products that do not have a real publish date, so website editing works smoothly even when sample products are used.
Original PR description
Currently, an error occurs when a user insert a dynamic product snippet onto website. **Steps to Reproduce:** - Install `website_sale` without demo data. - Go to `Website` > `eCommerce` > `Products`…
Currently, an error occurs when a user insert a dynamic product snippet onto website. **Steps to Reproduce:** - Install `website_sale` without demo data. - Go to `Website` > `eCommerce` > `Products` > `Ribbons`. - Open any ribbon and set `Assign` to `When New`. - Go to the `Website` > `Edit` > drag and drop the `Catalog` block, and select a `Dynamic Product` block (`Generic Product Template (customizable)` [ref](https://drive.google.com/file/d/1ZYeQA8DhfYAf_jbPwL-tZXaVi1YAyFbd/view?usp=drive_link)). `TypeError: unsupported operand type(s) for -: 'datetime.datetime' and 'bool'` After this [recent commit], when a user drops a dynamic product snippet, the system attempts to set the ribbon value [1]. If no product records are available, it falls back to using sample products [2]. These sample products are virtual records created with model.new() [3] [4] and are not stored in the database, so they do not have a publish date. When auto-assigned ribbon with the When New option assign, the system compares the ribbon's new period with the product's publish date. Since the sample products do not have a publish date, this comparison raises an error [5]. This commit ensures that the comparison between new period and publish date is only performed when the product has a valid publish date. [recent commit]: https://github.com/odoo/odoo/commit/f427f795c24ee37ee02302642b77bfc314a9ea43 [1]- https://github.com/odoo/odoo/blob/b70330df7dc2017ab592b075c8ad8e048f671d90/addons/website_sale/templates/snippets/product_snippet_template_data.xml#L52-L58 [2]: https://github.com/odoo/odoo/blob/b70330df7dc2017ab592b075c8ad8e048f671d90/addons/website/models/website_snippet_filter.py#L75-L78 [3]- https://github.com/odoo/odoo/blob/b70330df7dc2017ab592b075c8ad8e048f671d90/addons/website/models/website_snippet_filter.py#L210-L215 [4]: https://github.com/odoo/odoo/blob/b70330df7dc2017ab592b075c8ad8e048f671d90/addons/website_sale/models/website_snippet_filter.py#L62-L95 [5]: https://github.com/odoo/odoo/blob/b70330df7dc2017ab592b075c8ad8e048f671d90/addons/website_sale/models/product_ribbon.py#L121-L124 sentry-7528296918 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#268836
Debit notes sent to DIAN could fail because the XML included a field that this document type does not support. This fix removes that field for debit notes so the document can be created 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
This fix prevents returned products from being counted as received when the return operation is switched to a different delivery flow. It keeps purchase receipt totals accurate, avoiding incorrect overstatement of quantities received after returns.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Put your warehouse in delivery in 2 steps - On the receipt operation type change the return operation type to be "pick" by…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Put your warehouse in delivery in 2 steps - On the receipt operation type change the return operation type to be "pick" by default. - Create and confirm a PO for 1 unit of P - Validate the receipt > return > Create the return for 1 unit - Change the operation type of the return from Pick to Delivery to return the product in one step. - Validate the return #### > The qty_received is updated from 1 to 2 instead of 0. ### Cause of the issue: Updating the `picking_type_id` of the return will also update the `location_dest_id` to the default values: https://github.com/odoo/odoo/blob/89807c10c20fb533124b18815f307fc3c380528d/addons/stock/models/stock_picking.py#L1138-L1147 However, the default values of the `Delivery` is "Partner/customer". As such, the location dest of the move is also updated to be "Partner/customer". Now the issue is that the `qty_received` only considers moves to be returned if the location dest usage is not 'supplier': https://github.com/odoo/odoo/blob/89807c10c20fb533124b18815f307fc3c380528d/addons/purchase/models/purchase_order_line.py#L226-L231 https://github.com/odoo/odoo/blob/89807c10c20fb533124b18815f307fc3c380528d/addons/purchase_stock/models/purchase_order_line.py#L55-L67 https://github.com/odoo/odoo/blob/89807c10c20fb533124b18815f307fc3c380528d/addons/purchase_stock/models/purchase_order_line.py#L76-L77 https://github.com/odoo/odoo/blob/89807c10c20fb533124b18815f307fc3c380528d/addons/purchase_stock/models/stock_move.py#L129-L131 opw-6292918 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270571 Forward-Port-Of: odoo/odoo#269867
This change prevents the Intrastat report from failing when a company does not have a country selected. The report now uses the correct fallback value so the query runs successfully instead of stopping with a database error.
Original PR description
When there is no `country_id` on the company we get `False`. The generated query then fail at: ``` ... CASE WHEN (code.country_id IS NULL OR code.country_id = false) THEN code.code ELSE NULL END AS commodity_code, ... ``` with: ``` ERROR: operator does not exist: integer = boolean LINE 12: ... WHEN (code.country_id IS NULL OR code.country_id = false) T... ``` Forward-Port-Of: odoo/enterprise#121798 Forward-Port-Of: odoo/enterprise#121608
The Point of Sale now converts a product’s cost using the correct source currency instead of treating it the same as the sale price. This helps ensure that margin and cost-related figures shown in POS are more accurate when products use different currencies.
Original PR description
When loading products in the POS, both the sale price and the cost were converted to the POS currency using `currency_id`. However a product stores its sale price and its cost in two potentially different currencies: `currency_id` (company currency, falling back to the main company) and `cost_currency_id` (company currency, falling back to the current company). opw-6297452 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269829
This change fixes an error that could prevent the appraisal email template from being read correctly. As a result, appraisal-related emails can be prepared and sent without breaking the workflow.
Original PR description
Task#6309699 Forward-Port-Of: odoo/enterprise#121115
Attendance overtime rules now correctly respect employer tolerance when using timing-based rules. This prevents overtime from being created for short attendances that should fall within the allowed tolerance, improving payroll and attendance accuracy.
Original PR description
**Version:** - 19.0 **Steps to reproduce:** - Create a rule of Timing type. - Add a tolerance for the employer. - Set the ruleset on the employee. - Add an attendance of less than the tolerance. **Issue:** - When using a Timing type rule with employer tolerance, overtime is still created even if the attendance is below the tolerance limit. **Cause:** - The timing rule calculation was missing the tolerance check that exists in the quantity rule calculation. **Fix:** - Added the missing tolerance check in the timing rule calculation. - Removed employee tolerance from view for timing rules. **Task-6064081** Forward-Port-Of: odoo/odoo#271297 Forward-Port-Of: odoo/odoo#257079
The point of sale ticket screen now checks whether an order line is eligible for refund before adding it to a refund. This prevents refund orders from being refunded again and avoids duplicate refunds on lines that were already fully refunded.
Original PR description
In the ticket screen, clicking an order line selected it for refund and incremented its quantity without checking whether the line could actually be refunded. As a result, a refund order (whose lines carry a negative quantity) could itself be refunded, and already fully refunded lines could be refunded again. opw-6314527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271109
This update refreshes the spreadsheet component to the latest version and fixes a case where some accounting records use non-numeric identifiers. As a result, spreadsheet pivot data should load and normalize more reliably for affected accounting data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/e359501309 [REL] 19.4.1 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/e359501309 [REL] 19.4.1 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/5adffa5ca1 [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/feea883b1d [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
This fix corrects how user group access is calculated when a rule depends on access to a related model. It now combines the relevant group permissions properly, so access to records is granted only when both the implied groups and the related model permissions allow it.
Original PR description
When an access contains a domain `('comodel_id', 'access', 'read')`, the
model is not accessible for the group on that access. Instead, it is the
intersection of the implied groups and the groups that give access to
the comodel.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis fix makes the "undo reconciliation" action skip extra validation checks so the line can be reset correctly. It helps users reverse a reconciliation without getting blocked by conditions that are not needed for this action.
Original PR description
When undoing the reconciliation from the "undo reconciliation" button. We want to bypass all the checks to be able to reset the line. no task id Forward-Port-Of: odoo/enterprise#121611
This update ensures taxes created to apply everywhere are no longer lost when a fiscal position has no specific mapping. It also keeps the tax-related totals and buttons in sync after fiscal position changes, so users see the right tax options and accurate amounts.
Original PR description
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem…
A tax created without a fiscal position (empty fiscal_position_ids) is conceptually an "All" tax: it should apply across every fiscal position, including the empty ones used for tax units. Problem map_tax drops every tax when the FP has no mapping, including the "All" ones that should pass through. action_open_related_taxes only lists the FP's tax_ids, so "All" taxes are invisible from the FP form. The Taxes stat button is hidden whenever the FP has no tax_ids. action_update_fpos_values invokes the field computes directly, so tax and balance lines fall out of sync after an FP change. Fix map_tax: when the FP has no tax_ids, return the input taxes whose fiscal_position_ids is empty (the "All" ones) instead of an empty recordset. action_open_related_taxes: extend the domain to also include taxes bound to no fiscal position. partner_view: drop the invisible="not tax_ids" guard on the Taxes stat button. action_update_fpos_values: route the deferred computes through _check_balanced and _sync_dynamic_lines so tax lines stay in sync after the update. task-id [6231514](https://www.odoo.com/odoo/project/967/tasks/6231514) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272350 Forward-Port-Of: odoo/odoo#268273
This update prevents an access error that could block users from opening contacts in the kanban view when multiple companies are involved. It ensures meeting counts are calculated only with records the current user can access, so contact browsing stays smooth and reliable.
Original PR description
### Steps to reproduce: - Download Calendar and Contacts app - Go to the Setting -> Companies -> Manage companies; make sure there are at least two companies - Go to the Setting -> Users -> Manage…
### Steps to reproduce: - Download Calendar and Contacts app - Go to the Setting -> Companies -> Manage companies; make sure there are at least two companies - Go to the Setting -> Users -> Manage users; make sure the current logged-in user has access to both companies - Create a another user who also have access to both companies - Search for the new user in contacts -> Assign the current company to the contact -> Through the internal link of the company, go to sales and purchase tab -> assign the same company in the company field - Switch the company of the logged in user to the other company - Open the test contact form, use the meeting smart button and create a new meeting - Open the kanban contact view **> Access Error: Uh-oh! Looks like you have stumbled upon some top-secret records.** ### Cause of Issue: When trying to view the search results in kanban view, the `meeting_count` is calculated for each contact. Hence,`_compute_meeting_count()` is called which calls `_compute_meeting()`. https://github.com/odoo/odoo/blob/f39785bcddd1eb5b7fb503d053c9bb66e2a0f15c/addons/calendar/models/res_partner.py#L49-L54 Since the above section tries to access `partner.parent_id` each loop, it reaches a `parent_id` that's not accessible for the current user. ### Fix: Since we need to access `parent_id` to be able to calculate meeting count for the full tree of partners, `sudo()` is used to get all partners, but meetings are computed for ancestors who are in `self_ids` only so that we still remain within scope. Same old logic is used to propagate meetings for every ancestor, but dictionary lookups are used to enhance performance. opw-5874204 Forward-Port-Of: odoo/odoo#272832 Forward-Port-Of: odoo/odoo#248985
The website editor now keeps the page in desktop view when users edit at higher browser zoom levels. This prevents the page from unexpectedly switching to the mobile layout, improving consistency while editing.
Original PR description
Steps to reproduce: - Open a website page on Chrome/Firefox. - Set the browser zoom to 150%. - Click Edit. => The website preview switches to mobile view. Before this commit, [1] changed the sidebar to `content-box`, so the `border-start` class added one pixel to `$o-we-sidebar-width`. The sidebar then reached 289px instead of 288px, which made the preview fall below the desktop breakpoint at 150% zoom. After this commit, the sidebar width subtracts the Bootstrap border width so its total width stays at 288px and edit mode keeps the desktop view. [1]: https://github.com/odoo/odoo/commit/181b870c3c6cf28c3eac59a16c36b94ae11ae927 task-6251151 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272074
This change prevents PoS session closing from failing when the cash difference account has a default tax. It now calculates the tax-adjusted entries correctly from the start, so the closing move stays balanced and can be posted without errors.
Original PR description
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session,…
Steps to reproduce ------------------ 1. Set a default tax on the "Cash Difference Gain" account (e.g. a 25% sales tax) -- required in some countries like Denmark (cf 5972690). 2. Open a PoS session, count more cash than expected at closing. 3. Try to close the session. -> Error message shows up "The journal entry reached an invalid state..." ... "The journal entry must always have exactly one journal item involving the bank/cash account" What's happening ---------------- PoS creates a bank statement line with the gain account as counterpart, resulting in 2 lines: cash +10, gain -10. Since the gain account has a default tax, `_sync_tax_lines` adds a tax line of -2.5 on top, which makes the move unbalanced by 2.5. Then `_sync_unbalanced_lines` adds a 4th line to fix it, on the line returned by `_get_automatic_balancing_account`, which is `journal.default_account_id`, i.e. the cash account itself for a cash journal. So we end up with 2 lines on that same cash account, which a bank statement line move doesn't allow -> Error. The fix ------- In `_post_statement_difference`, precompute the base and tax split ourselves and build the statement line's `line_ids` directly (e.g. for +10 and a 25% tax: cash +10, gain -8, tax -2). The move is balanced from creation, so `_sync_tax_lines` and `_sync_unbalanced_lines` don't have to touch it. Note that we force the tax computation to be in 'force_price_include' mode, as the counted cash difference is a gross amount (physical money in the drawer). This way the tax is always extracted from the cash amount, regardless of how the tax is configured (included or excluded in price). Same pattern is already used by `hr_expense` (cf `hr_expense.models.account_move_line._compute_totals`). opw-5972690 Forward-Port-Of: odoo/odoo#271921 Forward-Port-Of: odoo/odoo#257892
This update fixes the due-date rules for Austrian VAT returns and EC sales lists. It replaces a simplified 15-day calculation with the correct month-based deadlines, helping ensure these filings are scheduled on time and in line with local requirements.
Original PR description
**[FIX] l10n_at_reports: correct Austrian return deadlines** The Austrian localization used a fixed `15 days` rule for both VAT returns and EC sales lists. This does not match the filing deadlines: the VAT return is due on the 15th day of the second following month while the EC sales list is due by the end of the following month (sources below). This fix replaces the hardcoded day offset with month-based deadline computation sources: https://www.usp.gv.at/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/umsaetze-mit-auslandsbezug/zusammenfassende-meldung-zm.html https://www.usp.gv.at/en/themen/steuern-finanzen/umsatzsteuer-ueberblick/weitere-informationen-zur-umsatzsteuer/entstehen-der-steuerschuld-und-pflichten/umsatzsteuervoranmeldung.html opw-6147343 Forward-Port-Of: odoo/enterprise#117212 Forward-Port-Of: odoo/enterprise#116212
11 changes
Enhancements to existing features
This change speeds up how Odoo retrieves task activity information used by the /mail/data endpoint. By adding a database index, the system can find the relevant records much faster, reducing wait times and improving overall responsiveness.
Original PR description
`/mail/data` is called a lot. It spends roughly 33% of its time on the query fetching task activities in `_get_activity_groups` https://github.com/odoo/odoo/blob/a52b277a4db5f14516717738ca962e3bb3c7180f/addons/project_todo/models/res_users.py#L27 This commit adds an index to speed up the query. - before ~25ms https://explain.dalibo.com/plan/72b26edce8448b51 - after <1ms https://explain.dalibo.com/plan/c4g6851e5b4hh702 task-6327159 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272712
Resolved issues and error corrections
This update fixes the Peru Kardex PLE stock report so it now calculates inventory values and opening balances correctly, even when later purchases change average cost. It also keeps special stock movements, like landed costs, visible in the report without requiring extra dependencies.
Original PR description
*Continuing on the work from https://github.com/odoo/enterprise/pull/111526, new PR because we cannot push to it.* Adapt the Kardex PLE 12.1/13.1 reports from the SVL-based approach in 18.0 to the stock.move-based approach required in 19.0. Key changes: - Use traceable IDs (account_move_id/stock_move_id) for CUO field - Back-calculate opening balance cost at report date instead of using current standard_price, which is wrong when post-period purchases have changed the average cost - Filter storable products only (is_storable) matching v17/v18 behavior - Handle negative opening balance quantities correctly - Add bridge module l10n_pe_reports_stock_landed_costs to show landed costs as separate Kardex lines (operation_type=26) without forcing stock_landed_costs as a hard dependency Forward-Port-Of: odoo/enterprise#121855
This update fixes an issue where invoices sent to Viettel S-Invoice could fail when the returned ZIP file had a different structure than expected. The system now correctly finds the XML whether it is directly in the ZIP or inside nested ZIP files, preventing errors and improving reliability.
Original PR description
Description of the issue/feature this PR addresses: The actual XML extraction hardcoded the double-zipped case by reading only the first entry of the outer zip (`zip_file.infolist()[0]`), assuming it…
Description of the issue/feature this PR addresses: The actual XML extraction hardcoded the double-zipped case by reading only the first entry of the outer zip (`zip_file.infolist()[0]`), assuming it was always a nested zip containing the XML. This made it fail when: - The XML was directly in the outer zip (single-zipped). - The zip contained multiple files and the first nested zip didn't hold the XML. Current behavior before PR: After sending an Invoice to Viettel S-Invoice, the e-Invoicing platform would return a ZIP containing one XML file. The XML File being double-unzipped, a traceback is raised. Desired behavior after PR is merged: The fix rewrites _recursive_zip_xml_file_data to actually be recursive. Invoices can be sent to Viettel S-Invoice without raising a traceback. opw-[6249929](https://www.odoo.com/odoo/project.task/6249929?debug=1) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272121 Forward-Port-Of: odoo/odoo#268482
Planning reports can now be printed safely even when grouped by fields like Role or Project instead of Employee. This prevents crashes during report generation and ensures multi-day shifts are handled correctly, improving reliability for users who rely on customized planning views.
Original PR description
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or…
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or `AttributeError`. ### Cause: The `action_print_plannings` method hardcoded the assumption that the `group_by` key would always be a `resource.resource` recordset. 1. When the user grouped by other fields, it returned strings, booleans, or empty recordsets, causing crashes when the code blindly called `.id` and `.display_name`. 2. During the sorting phase, mixing `False` (for unassigned empty recordsets) with strings caused a `TypeError`. 3. For multi-day shifts, the method failed to extract the actual resource to calculate the shift splits if the grouping was not explicitly set to `resource_ids`. ### Fix: - Implement safe attribute checks (`hasattr`) when extracting group IDs and display names. - Ensure unassigned empty recordsets properly fall back to the "Undefined" string and empty strings during sorting to prevent TypeErrors. - Universally fallback to extracting the resource directly from the slot (`slot.resource_ids[:1]`) for multi-day time splitting when grouped by non-resource fields. - Add a unit test to ensure stability when grouping by `role_id` with multi-day shifts. Task: 6244057 Forward-Port-Of: odoo/enterprise#118530
This change prevents an error that could occur when the system looked up an IoT device and found more than one match. It makes device access more reliable by ensuring only one device record is used, avoiding interruptions for users relying on IoT features.
Original PR description
Currently, a singleton error occurs while accessing the `type` field on `iot_device`, as the search assigned to `iot_device` returns multiple `iot.device` records. Error: `ValueError: Expected singleton: iot.device(5, 10)` This commit fixes the above issue by adding `limit=1` to the search, ensuring that `iot_device` always contains a single record and preventing the singleton error. Sentry-7579060623 Forward-Port-Of: odoo/enterprise#122219
This change fixes an issue that could prevent managers from creating a group time off request for multiple employees. If no time-off work type is configured, the system now handles that case safely instead of showing an error.
Original PR description
Currently, an error occurs when a user tries to create a group time off. **Steps to Reproduce:** - Install the `hr_presence` module without demo data. - Go to `Employees` > `Configuration` > `Working…
Currently, an error occurs when a user tries to create a group time off. **Steps to Reproduce:** - Install the `hr_presence` module without demo data. - Go to `Employees` > `Configuration` > `Working Times` > `Time Types` and delete all records. - Make sure there are at least `two employee` records. - Go to `Employees` and switch to the `list view`. - Select `both employees` > click `Presence Control` > click `Create a Time Off`. **Error1:** `TypeError: unsupported operand types in: hr.work.entry.type() | None` **Error2:** `AttributeError: 'NoneType' object has no attribute 'ids'` When a user creates a group time off record and the wizard is opened, it computes the valid work entry types. If no work entry type exists, accessing the `True` key (`requires_allocation`) from the empty dictionary returns None [1]. Later, when performing a union (|) between an empty work entry type recordset and None, it raises the first error [2]. Additionally, accessing ids on None raises the error [3]. This commit ensures that when no work entry type exists, accessing key(requires_allocation) from an empty dictionary returns an empty work entry type record instead of None. [1]- https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L144-L145 [2]- https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L146 [3]: https://github.com/odoo/odoo/blob/374f48cfba75ff98f53d8c3fcc51847711bd406a/addons/hr_holidays/wizard/hr_leave_generate_multi_wizard.py#L148 sentry-7552717400 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue where rental and non-rental quotations linked to an opportunity could disappear from the Quotation list. This ensures users can correctly review all expected quotations from the opportunity, improving visibility and day-to-day sales follow-up.
Original PR description
Steps to reproduce: 1. Install sale_crm and sale_renting_crm 2. Create an opportunity 3. On this opportunity, create two quotations from the `New quotation` button 4. From the opportunity's form…
Steps to reproduce:
1. Install sale_crm and sale_renting_crm
2. Create an opportunity
3. On this opportunity, create two quotations from the `New quotation` button
4. From the opportunity's form view, click on the `Quotation` smart button
Issue:
- The quotations are not visible in the list view
Why?
- In module `sale_renting_crm`, we override the domain to exclude rental quotations.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting_crm/models/crm_lead.py#L33-L36 But from the saas-19.3 `is_rental_order` field is no longer stored in the DB, It is computed now and filtered through `_search_is_rental_order`.
https://github.com/odoo/enterprise/blob/fda037c62a6661665611fb061718c01aec39ac1b/sale_renting/models/sale_order.py#L223-L227 The search method did not properly handle the Boolean search shape used by the ORM, so the quotations were incorrectly filtered out. In our case, we gave the domain `("is_rental_order", "=", False)` but the operator is translated to `not in` and value to `Orderedset([True])` by the domain optimiser
Solution:
- Update `_search_is_rental_order()` to handle the ORM-normalized boolean search correctly for rental and non-rental quotations.
opw-6304696This update refreshes the spreadsheet component and fixes an issue that could prevent certain accounting data from being handled correctly. It improves how spreadsheet pivot tables interpret data, which helps reports display more reliably for affected users.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/040ae04f23 [REL] 19.3.10 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/040ae04f23 [REL] 19.3.10 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/37a0a7031f [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/3412fa57da [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
This fix prevents a crash when translating report XML in Studio on databases where English is not installed. It makes the translation flow more reliable for users working in other base languages.
Original PR description
Init a db with a language different from en_US install other languages, except en_US Try to translate via studio a report's XML This gives a crash, because the baseLang is not installed After this commit, there is no crash. opw-6239938 Forward-Port-Of: odoo/enterprise#122026
When a sign template is duplicated, its roles are now copied as well instead of being shared with the original template. This prevents changes made to one template from unexpectedly affecting another, keeping each template independent.
Original PR description
When duplicating a sign template, its sign items were copied but their `responsible_id` was kept as a reference to the same `sign.item.role` records. As a result, editing a role on one template (e.g. assigning a partner through `assign_to`) leaked to the other template sharing it. Copy the role when copying a sign item so each template owns its own roles. task-6288951 Forward-Port-Of: odoo/enterprise#121411 Forward-Port-Of: odoo/enterprise#119864
This change prevents errors when users work with products that do not yet have a generated variant. It hides or blocks inventory-related actions that depend on a variant, avoiding broken forecast, replenish, and on-hand quantity behavior.
Original PR description
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1-…
Issue: --- Not having at least one variant created for a product template with dynamic attributes can cause issues as it's expected a product template to have at least one variant. To reproduce: 1- Create a dynamic attribute with values. 2- Create a product and without saving: - Enable track inventory. - Add the dynamic attributes and values. 3- Save the product. 4- Click on forecasted quantity smart button: - There is a traceback. 5- Click on Replenish: - Unexpected behavior. 6- Click on `Product On Hand Quantity`: - No product will be shown if you try to add quantity. Cause: --- This is caused because there is no variant created. In the steps, if you save the template once before adding dynamic attributes, a single variant will be created which allows it to work without issue. Fix: --- we can fix the TB by hiding the forecasted qty smart button, when there is no variant. However, there will be still issue with `Replenish` flow, which requires a variant. We could do the prevent the issue by ensuring there is at least one variant. opw-6260253 Forward-Port-Of: odoo/odoo#272943 Forward-Port-Of: odoo/odoo#268879
7 changes
Resolved issues and error corrections
This update prevents an error that could appear when the system looks up an IoT device. It ensures only one matching device is used, which helps avoid unexpected interruptions when accessing IoT features.
Original PR description
Currently, a singleton error occurs while accessing the `type` field on `iot_device`, as the search assigned to `iot_device` returns multiple `iot.device` records. Error: `ValueError: Expected singleton: iot.device(5, 10)` This commit fixes the above issue by adding `limit=1` to the search, ensuring that `iot_device` always contains a single record and preventing the singleton error. Sentry-7579060623 Forward-Port-Of: odoo/enterprise#122219
This change fixes a problem where previewing a webhook sample payload could fail for some records. The preview now handles complex field values correctly, so users can view webhook examples without encountering an error.
Original PR description
**Steps to Reproduce:** - Create a Server Action of type 'Webhook Notification'. - Select a model containing a field that returns a `frozendict`-based structure (e.g. `account.move` →…
**Steps to Reproduce:** - Create a Server Action of type 'Webhook Notification'. - Select a model containing a field that returns a `frozendict`-based structure (e.g. `account.move` → `needed_terms`). - Add the field to the webhook fields. - Open the webhook sample payload preview. **Issue:** - During sample payload generation: - The selected fields are read from a sample record. - A selected field returns a structure containing `frozendict` objects. - The payload is serialized using `json.dumps()`. - JSON serialization fails with: ```text TypeError: keys must be str, int, float, bool or None, not frozendict ``` - The webhook sample payload computation crashes and the preview cannot be displayed. **Root Cause:** - The webhook sample payload may contain `frozendict` objects returned by selected fields. - The serializer used for payload generation does not handle such mapping-like objects, causing `json.dumps()` to fail. **Solution:** - Use a serializer that converts mapping-like objects into JSON-compatible structures before serializing the webhook sample payload. **OPW-6295777** 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#272324 Forward-Port-Of: odoo/odoo#271864
This update fixes a spreadsheet issue where some accounting data could not be processed correctly because certain record IDs are text instead of numbers. It helps spreadsheets handle these records properly, improving reliability when working with accounting-related data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/3529978d50 [REL] 19.2.19 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/3529978d50 [REL] 19.2.19 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/156b8921dc [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/f3ae8587f9 [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
This update prevents overtime work intervals from slightly overlapping when times are reconstructed from rounded durations. It improves the accuracy of attendance-based work entries, avoiding small timestamp conflicts that could affect payroll and scheduling records.
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
When a new file is uploaded in Documents, its action buttons now appear immediately. This removes the need to deselect and reselect the file just to access available actions, making file handling smoother and faster.
Original PR description
Bug === When uploading a new file in documents, it's selected, but the actions are not visible (we need to unselect - select the record to see the actions). Task-5408471 Forward-Port-Of: odoo/enterprise#122102 Forward-Port-Of: odoo/enterprise#114770
This update corrects how emoji shortcuts are handled in the text editor so they work more reliably within a paragraph, not only at the end of a line. It also prevents the editor’s command popup from opening incorrectly when an emoji replaces a slash, which avoids distracting and unexpected behavior for users.
Original PR description
#### Description of the issue this PR addresses: - When an emoji shortcut ending with `/` (e.g. `:/` for 😕) is typed, the emoji plugin replaces the characters before the powerbox `on_input_handler`…
#### Description of the issue this PR addresses: - When an emoji shortcut ending with `/` (e.g. `:/` for 😕) is typed, the emoji plugin replaces the characters before the powerbox `on_input_handler` runs. Since `ev.data` still reflects the original typed `/`, the powerbox was incorrectly opening. - Emoji shortcuts works only when it is used at the end of a text node, because the matching logic checked the whole remaining substring from the current position. - Sometimes, pressing Backspace splits one text node into two, and then an emoji shortcut works at the end of the first text node even when the paragraph is visible as a single line. #### Desired behavior after PR is merged: - Check the DOM character at cursor position instead of `ev.data` to determine whether `/` is actually present before opening the powerbox. - Emoji shortcuts now works when used with a preceding space anywhere in the paragraph. Enterprise PR-https://github.com/odoo/enterprise/pull/118310 task-6243724 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update stops Instagram post creation from failing with a server crash when Instagram takes too long to fetch an image. Instead, the post is marked as failed with a clear message, helping users understand what went wrong and try again with a smaller image if needed.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#112573
7 changes
Enhancements to existing features
When selling products tracked by lot or serial number, the system now automatically applies the correct lot for FIFO/LIFO products and adds them to the cart without extra prompts. If no removal strategy is set, the current selection popup still appears, so existing workflows remain unchanged.
Original PR description
Before this commit: ==== - The lot/serial selection popup was always shown when adding products tracked by lots. Following this commit: ==== - Products configured with FIFO/LIFO removal strategies are automatically assigned the corresponding lot and added directly to the cart without opening the selection popup. - If no removal strategy is configured, the existing lot selection behavior is preserved. task-6226577 Forward-Port-Of: odoo/odoo#265708
Resolved issues and error corrections
This update prevents an error that could happen when a user removes the currency in the payment registration screen. It improves the payment flow for the Argentine withholding setup by avoiding a crash and letting the form handle an empty currency correctly.
Original PR description
When the user removes the currency from the payment register, a traceback is raised. Steps to reproduce the error: - Install ``l10n_ar_withholding`` module - Switch to ``(AR) Exento`` company - Create a new invoice > Confirm > Pay > Unset the currency Traceback: ```py ValueError: Expected singleton: res.currency() ``` https://github.com/odoo/odoo/blob/d98afdc08b46bf458eaa287ea882cc7663286a59/addons/l10n_ar_withholding/wizards/account_payment_register.py#L27 This line causes a traceback with an empty currency when the user removes the currency from the payment register. sentry-7362499567 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272634 Forward-Port-Of: odoo/odoo#255825
When a new file is uploaded in Documents, the available actions are now shown immediately after the file is selected. This removes the extra step of deselecting and reselecting the file just to access its actions, making the workflow smoother and faster for users.
Original PR description
Bug === When uploading a new file in documents, it's selected, but the actions are not visible (we need to unselect - select the record to see the actions). Task-5408471 Forward-Port-Of: odoo/enterprise#122102 Forward-Port-Of: odoo/enterprise#114770
This update refreshes the spreadsheet component to its latest version and includes fixes for how pivot data is processed. It also improves compatibility with records that use non-numeric identifiers, helping avoid errors when working with certain accounting data.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/44237c04a0 [REL] 19.1.26 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/44237c04a0 [REL] 19.1.26 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/ac1974039f [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/9fa87aa588 [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Instagram posts with images will now fail gracefully if the connection times out or another network issue occurs, instead of crashing the server. Users will see a proper failed status, with clearer guidance when the issue is likely caused by a large image taking too long to process.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#112573
This change fixes an issue that could make the sales order line screen crash when opening certain order-editing flows. It ensures the product information needed by the unit-of-measure widget is included, so users can load and edit sales lines without encountering an error.
Original PR description
Description of the issue/feature this PR addresses:
- The mandatory product_id field required by the many2one_uom widget was omitted from the list view, causing the issue.
- The issue occurred when the customized 'Extend Order' button was clicked, opening the wizard with all sales order lines loaded into its one2many field.
- Error message: UncaughtPromiseError > OwlError
Uncaught Promise > An error occured in the owl lifecycle (see this Error's "cause" property)
Occured on apollohomecare-migration-v19-33341368.dev.odoo.com on 2026-06-26 10:18:38 GMT
OwlError: An error occured in the owl lifecycle (see this Error's "cause" property)
Error: An error occured in the owl lifecycle (see this Error's "cause" property)
Caused by: Error: The widget 'Many2OneUomField' (field 'product_uom_id') needs a 'product.product' or 'product.template' field. 'product_id' is used but is related to an 'undefined' model.Payslips created from a parent company will now correctly show employees from its Belgian branch companies. This fixes a filtering issue so payroll users can select the right employees without missing branch staff.
Original PR description
Bug: employees registered on branch companies don't appear in the
employee_id field when creating a payslip from the parent company.
Reason: the domain used ('company_id', '=', company_id) which only
matches the exact company, not its children.
Solution: replaced '=' with 'child_of' to include all descendant
companies in the hierarchy.
task - 6299634
Forward-Port-Of: odoo/enterprise#121360
Forward-Port-Of: odoo/enterprise#1209745 changes
Resolved issues and error corrections
This update fixes an issue that could prevent PDF generation for certain Guatemala vendor bills, especially those using the FESP document type with withholding taxes. Users can now download the invoice PDF successfully without encountering errors.
Original PR description
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding…
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding 12%` and `ISR Withholding 5%` in Invoice lines. - `Confirm` the bill and `Send to SAT`. - From the gear icon, click `Download` > `PDF`. **Error1:** `KeyError: 'gran_total'` **Error2:** `KeyError: 'retencion_grand_total'` **Root Cause:** In commit [1], the code at [2] missed calling `_l10n_gt_edi_add_base_values()` before `_l10n_gt_edi_add_withholding_values()`. However, `_l10n_gt_edi_add_withholding_values()` uses the `gran_total` value, which is initialized by `_l10n_gt_edi_add_base_values()`, resulting in a `KeyError`. Additionally, the report template at [3] references `retencion_grand_total` instead of the correct key `retencion_gran_total`, causing another `KeyError`. **Fix:** This commit prevents errors and ensures users can successfully download the PDF by applying a fix similar to [4], [1]: https://github.com/odoo/enterprise/commit/44afd19e4ed0827e343af0e584c81e579935c9e8 [2]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L305-L328 [3]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/views/report_invoice.xml#L72 [4]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L790-L800 opw-6323049 Forward-Port-Of: odoo/enterprise#122030
The Helpdesk ticket quick-create form now limits the customer list to the selected company. This prevents users working across multiple companies from accidentally choosing a customer that belongs to a different company.
Original PR description
Steps to reproduce: - Create two companies (Company A and Company B) - Create one partner in each company - Enable both companies for the user - Open Helpdesk and go to the tickets Kanban view for a Company A team. - In the quick create form, the customer dropdown shows customers from Company B Issue: - Customers from other companies are visible in the customer field, Cause: - The partner_id field in the quick create view had no domain, so it displayed partners from all allowed companies. Solution: - Added a domain on partner_id in the ticket quick create form view. task-4971466 Forward-Port-Of: odoo/enterprise#121944
This update prevents a traceback when users enter a negative forecast demand in the last planning period. It also ensures any remaining negative quantity is applied to the first forecast, so planning behaves as intended and does not break.
Original PR description
Steps to reproduce: - Fresh DB - Add a negative number to the forecast demand in the last period Cause: A variable was used without declaration Fix: According to odoo/enterprise#56128, it was intended that any remaining negative quantity to add should be added to the first forecast. Forward-Port-Of: odoo/enterprise#122261
Posting an Instagram image could previously crash the request if Instagram took too long to fetch the image from Odoo. This change catches those network errors, marks the post as failed, and shows a clearer message so users can retry with a smaller image if needed.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#112573
Payslips created at a parent company will now correctly include employees assigned to its branch companies. This fixes an inconsistency that could prevent the right employee from being selected when processing payroll in Belgian company structures.
Original PR description
Bug: employees registered on branch companies don't appear in the
employee_id field when creating a payslip from the parent company.
Reason: the domain used ('company_id', '=', company_id) which only
matches the exact company, not its children.
Solution: replaced '=' with 'child_of' to include all descendant
companies in the hierarchy.
task - 6299634
Forward-Port-Of: odoo/enterprise#121360
Forward-Port-Of: odoo/enterprise#1209748 changes
Resolved issues and error corrections
The Helpdesk quick-create form now only shows customers that belong to the selected company. This prevents users working across multiple companies from accidentally choosing a customer from the wrong one.
Original PR description
Steps to reproduce: - Create two companies (Company A and Company B) - Create one partner in each company - Enable both companies for the user - Open Helpdesk and go to the tickets Kanban view for a Company A team. - In the quick create form, the customer dropdown shows customers from Company B Issue: - Customers from other companies are visible in the customer field, Cause: - The partner_id field in the quick create view had no domain, so it displayed partners from all allowed companies. Solution: - Added a domain on partner_id in the ticket quick create form view. task-4971466 Forward-Port-Of: odoo/enterprise#121944
This change fixes an issue that prevented users from downloading the PDF of certain Guatemala vendor bills. It ensures the report is generated correctly so businesses can access and share the document without errors.
Original PR description
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding…
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding 12%` and `ISR Withholding 5%` in Invoice lines. - `Confirm` the bill and `Send to SAT`. - From the gear icon, click `Download` > `PDF`. **Error1:** `KeyError: 'gran_total'` **Error2:** `KeyError: 'retencion_grand_total'` **Root Cause:** In commit [1], the code at [2] missed calling `_l10n_gt_edi_add_base_values()` before `_l10n_gt_edi_add_withholding_values()`. However, `_l10n_gt_edi_add_withholding_values()` uses the `gran_total` value, which is initialized by `_l10n_gt_edi_add_base_values()`, resulting in a `KeyError`. Additionally, the report template at [3] references `retencion_grand_total` instead of the correct key `retencion_gran_total`, causing another `KeyError`. **Fix:** This commit prevents errors and ensures users can successfully download the PDF by applying a fix similar to [4], [1]: https://github.com/odoo/enterprise/commit/44afd19e4ed0827e343af0e584c81e579935c9e8 [2]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L305-L328 [3]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/views/report_invoice.xml#L72 [4]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L790-L800 opw-6323049 Forward-Port-Of: odoo/enterprise#122030
This fix prevents a traceback that could happen when a negative forecast demand is entered in the last period. It also ensures any remaining negative quantity is correctly applied to the first forecast, preserving the intended planning behavior.
Original PR description
Steps to reproduce: - Fresh DB - Add a negative number to the forecast demand in the last period Cause: A variable was used without declaration Fix: According to odoo/enterprise#56128, it was intended that any remaining negative quantity to add should be added to the first forecast. Forward-Port-Of: odoo/enterprise#122261
The spreadsheet component has been updated to the latest version, bringing the latest fixes and maintenance changes. It also improves how pivot tables handle certain records, which helps avoid display or calculation issues in some accounting-related spreadsheets.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/d00e4b62c5 [REL] 18.3.54 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/d00e4b62c5 [REL] 18.3.54 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/722416eaf1 [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/5c888b116c [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Posting an Instagram update with an image no longer risks crashing the server when Instagram takes too long to fetch the image. Instead, the post is now marked as failed with a clearer message, helping users retry with a smaller image or try again later.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#112573
This fix keeps the rating menu in sync with the messaging behavior so users can open notification messages correctly. It prevents the rating extension from overriding the normal fallback, which avoids sending users to the wrong conversation view.
Original PR description
Description of the issue/feature this PR addresses: The rating module does not correctly extend the mail modules onClick for NotificationItem Current behavior before PR: * mail NotificationItem…
Description of the issue/feature this PR addresses:
The rating module does not correctly extend the mail modules onClick for NotificationItem
Current behavior before PR:
* mail NotificationItem onClick calls `this.onClickThread(isMarkAsRead, thread, message)`
* rating NotificationItem onClick calls `this.onClickThread(isMarkAsRead, thread)`
* causing the [if in onClickThread](https://github.com/odoo/odoo/blob/18.0/addons/mail/static/src/core/public_web/messaging_menu.js#L39C17-L39C24) to be missed and falling backup to opening the thread
```javascript
if (message?.needaction && message.message_type === "user_notification") {
this.store.inbox.highlightMessage = message;
this.openDiscussion(this.store.inbox);
return;
}
this.openDiscussion(thread);
return;
```
Desired behavior after PR is merged:
* rating should not change the fallback behaviour for messages without a rating_id and still allow opening the user_notification in inbox instead of switching to the thread
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Info @wt-io-it
Forward-Port-Of: odoo/odoo#244521The email shown on signature certificates is now taken from the applicant’s actual email instead of a fallback value. This ensures recruitment offers signed through Sign display the right contact information and avoids confusing mismatches in records.
Original PR description
When generating an offer from the recruitment application and signing it, the applicant's email address is incorrectly displayed. ### **Steps to Reproduce:** 1) Install sign, recruitment,…
When generating an offer from the recruitment application and signing it, the applicant's email address is incorrectly displayed. ### **Steps to Reproduce:** 1) Install sign, recruitment, hr_contract_salary 2) Create an new application and add basic detail like name and email as (path and `path@test.com`) 3) Generate offer and sign with all the required signer(applicant and Marc Demo). 4) Open the application form view and open the certificate. ### **Observed Behavior:** Email is not set correctly in the generated certificate (appearing as `john@example.com`). ### **Expected Behavior:** The email of the applicant should be correctly set(e.g as `path@test.com`) ### **Root Cause:** When the applicant signs the document, their email is explicitly set to `False` at [1]. This is done because the applicant is not linked to any user yet. Later, when generating the certificate, the system attempts to display the user's partner email at [2], which is `False`, causing the default fallback value (`john@example.com`) to be printed. [1]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/hr_contract_salary/controllers/main.py#L53-L54 [2]- https://github.com/odoo/enterprise/blob/49226f4109c7d7bb48340949951e70f4245d0e5b/sign/report/sign_log_reports.xml#L59 ### **Fix:** Use `signer_email` instead of the partner's email to ensure the correct email is displayed on the certificate every time. opw-6280170 Forward-Port-Of: odoo/enterprise#120566
This change prevents invoices from crashing when a user removes the currency after choosing a payment term. If no currency is selected, the system now safely uses the journal or company currency as a fallback so payment terms can still be computed without error.
Original PR description
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new…
Currently, an error occurs on an invoice when user selects a payment term and removes the currency. Steps to replicate: - Install account - Turn on multiple currencies - Open invoices. - Create a new invoice - Add a line - Add a customer - Save - Select payment term as `30% Now, Balance 60 Days` - Remove the currency. Error: ``` ValueError: Expected singleton: res.currency() ``` Cause: - This error only occurs when the selected payment term contains at least two due term lines [1]. - When the selected payment term has atleast two lines the check [1] assigns `on_balance_line` as false and the `else` block is evaluated where currency being an empty recordset (as the user removed it) causes the error from [line] when trying to perform `round()` on an empty res.currency recordset. Solution: - As the currency is a required field, user will not be able to save the record until a currency is assigned. - Used journal's currency or company's currency as a fallback when computing payment terms if the current currency is empty. [1]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L229 [line]: https://github.com/odoo/odoo/blob/177002c0aca95de2de6458bb65bedf5c74541ac0/addons/account/models/account_payment_term.py#L240 sentry-7569922293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272073
3 changes
Resolved issues and error corrections
When creating a Helpdesk ticket quickly, the customer list is now limited to the correct company. This prevents users from accidentally selecting a customer that belongs to another company.
Original PR description
Steps to reproduce: - Create two companies (Company A and Company B) - Create one partner in each company - Enable both companies for the user - Open Helpdesk and go to the tickets Kanban view for a Company A team. - In the quick create form, the customer dropdown shows customers from Company B Issue: - Customers from other companies are visible in the customer field, Cause: - The partner_id field in the quick create view had no domain, so it displayed partners from all allowed companies. Solution: - Added a domain on partner_id in the ticket quick create form view. task-4971466 Forward-Port-Of: odoo/enterprise#121944
This update prevents a crash when a negative forecast demand is entered in the last planning period. Any remaining negative quantity is now correctly applied to the first forecast, so planning stays usable and results remain consistent.
Original PR description
Steps to reproduce: - Fresh DB - Add a negative number to the forecast demand in the last period Cause: A variable was used without declaration Fix: According to odoo/enterprise#56128, it was intended that any remaining negative quantity to add should be added to the first forecast. Forward-Port-Of: odoo/enterprise#122261
Posting an Instagram message with an image could previously trigger an unhandled network timeout and disrupt the server. This change catches those errors, marks the post as failed, and shows a clearer message so users can retry with a smaller image if needed.
Original PR description
Making an Instagram containing an image can crash the server with an unhandled `ReadTimeout` instead of marking the post as failed. ### Cause When creating a media container, Odoo passes a URL pointing to its own server and Instagram fetches the image from it server-side before responding. The timeout therefore covers network latency, Instagram's download speed from the Odoo server, and image processing time, making it prone to being exceeded. When it is, `requests` raises a `ReadTimeout` which is unhandled, leading to a raw RPC error instead of a clean `state='failed'`. ### Fix Catch the network errors and mark the post as failed instead of letting them crash the request. Timeouts get a message suggesting a smaller image, since they are usually caused by Instagram fetching and processing a large image server-side. Any other request error falls back to a generic message. opw-6015997 Forward-Port-Of: odoo/enterprise#112573
8 changes
Enhancements to existing features
Users can now see product availability and expected arrival information directly in the stock move list view for planned field service sales orders. This removes the need to open each record just to check replenishment timing, making it faster to review pending deliveries.
Original PR description
Previously, when a sales order for a field service product was planned, adding supplementary products only displayed the basic delivery status in the stock moves list view. To view the replenishment forecast or expected arrival date, users had to navigate into the form view. - This commit exposes the `forecast_widget` in the list view. Users can now check product availability and arrival timelines at a glance without opening individual records. task-5929015
Resolved issues and error corrections
Printing the Planning report now works reliably even when the report is grouped by fields such as Role or Project instead of Employee. This prevents crashes during PDF generation and ensures multi-day shifts are split correctly in all grouping modes.
Original PR description
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or…
### Issue: When printing the Planning report (PDF) and grouping by a field other than Employee (e.g., Role, Project, or a Char/Selection field), the server crashes with a `TypeError` or `AttributeError`. ### Cause: The `action_print_plannings` method hardcoded the assumption that the `group_by` key would always be a `resource.resource` recordset. 1. When the user grouped by other fields, it returned strings, booleans, or empty recordsets, causing crashes when the code blindly called `.id` and `.display_name`. 2. During the sorting phase, mixing `False` (for unassigned empty recordsets) with strings caused a `TypeError`. 3. For multi-day shifts, the method failed to extract the actual resource to calculate the shift splits if the grouping was not explicitly set to `resource_ids`. ### Fix: - Implement safe attribute checks (`hasattr`) when extracting group IDs and display names. - Ensure unassigned empty recordsets properly fall back to the "Undefined" string and empty strings during sorting to prevent TypeErrors. - Universally fallback to extracting the resource directly from the slot (`slot.resource_ids[:1]`) for multi-day time splitting when grouped by non-resource fields. - Add a unit test to ensure stability when grouping by `role_id` with multi-day shifts. Task: 6244057 Forward-Port-Of: odoo/enterprise#118530
This update corrects the Peru Kardex PLE stock report so it produces more accurate inventory and cost figures. It also ensures landed costs appear properly in the report without adding an unnecessary hard dependency, which improves reliability and compatibility in daily reporting.
Original PR description
*Continuing on the work from https://github.com/odoo/enterprise/pull/111526, new PR because we cannot push to it.* Adapt the Kardex PLE 12.1/13.1 reports from the SVL-based approach in 18.0 to the stock.move-based approach required in 19.0. Key changes: - Use traceable IDs (account_move_id/stock_move_id) for CUO field - Back-calculate opening balance cost at report date instead of using current standard_price, which is wrong when post-period purchases have changed the average cost - Filter storable products only (is_storable) matching v17/v18 behavior - Handle negative opening balance quantities correctly - Add bridge module l10n_pe_reports_stock_landed_costs to show landed costs as separate Kardex lines (operation_type=26) without forcing stock_landed_costs as a hard dependency Forward-Port-Of: odoo/enterprise#121855
This update prevents an error that could occur when the system fetched an IoT device record and found more than one match. It makes the lookup return just one device, improving reliability and avoiding interruptions in IoT-related workflows.
Original PR description
Currently, a singleton error occurs while accessing the `type` field on `iot_device`, as the search assigned to `iot_device` returns multiple `iot.device` records. Error: `ValueError: Expected singleton: iot.device(5, 10)` This commit fixes the above issue by adding `limit=1` to the search, ensuring that `iot_device` always contains a single record and preventing the singleton error. Sentry-7579060623 Forward-Port-Of: odoo/enterprise#122219
Users can now select accounts with the Other Expenses type when creating financial budget lines. This aligns budget setup with all profit and loss accounts, making budgeting more complete and avoiding a selection blocker.
Original PR description
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and…
Currently, accounts with the `Other Expenses` account type cannot be selected in financial budget lines. **Steps to reproduce:** - Install the `accountant` module. - Go to `Chart of Accounts` and create a new account with `Type: Other Expenses`. - Go to Accounting > Configuration > Financial Budgets. - Create a new budget and add a budget line. - Try to select the newly created account. **Observation:** Accounts with the `Other Expenses` type are not available for selection in budget lines. **Root Cause:** At [1], the `expense_other` account type is missing from the `account_id` domain. **Expected Behavior:** Financial budgets should allow all Profit & Loss accounts, since the feature relies on P&L reporting. **Reference**: https://www.odoo.com/odoo/project/49/tasks/4314709 **Fix:** This commit ensures that users can add `Other Expenses` accounts to budget lines. [1]: https://github.com/odoo/enterprise/blob/41b66ba081f3938f7e55da209506c637850ae4ec/account_reports/models/budget.py#L114-L120 opw-6313835 Forward-Port-Of: odoo/enterprise#121735
This update corrects button and keypad visibility issues in the Point of Sale ticket screen for certain local setups. It ensures the right controls appear only when they should, and also improves the appearance of a prep-order input field in dark mode.
Original PR description
Issue 1: ====== Numpad Visibility in TicketScreen of draft urban piper orders Steps to reproduce: =================== - Ensure `pos_hr` and `pos_urban_piper` is installed. - Install…
Issue 1: ====== Numpad Visibility in TicketScreen of draft urban piper orders Steps to reproduce: =================== - Ensure `pos_hr` and `pos_urban_piper` is installed. - Install `l10n_in_pos_urban_piper`. - Open a draft Urban Piper order and notice that the numpad is visible. Cause: ====== - The numpad visibility depends on a `t-if` condition in XML. - Due to the asset loading order, this condition gets overridden by another module. Fix: ==== - Move the visibility logic to a getter method. - Override the getter in other modules instead of using XML to control the visibility. - Also fixed the css issue for prep order time input when using it in dark mode --- Issue 2: ====== Invoice button visible on Chile Company's TicketScreen Steps to reproduce: =============== - Ensure `pos_urban_piper` is installed, open the Chile company's PoS Config - In the ticket screen, we have an invoice button on paid orders. Cause: ===== - Button visibility handled through XML conditions; this condition gets overridden by another module. Fix: === - Move the visibility logic to the getter method and override it in submodules to control visibility. Task-6299415 Related Community PR: https://github.com/odoo/odoo/pull/270088 Forward-Port-Of: odoo/enterprise#120571
Quality emails sent to an alias are now correctly turned into quality alerts even when the team’s company was not set. This prevents incoming messages from being lost and helps ensure issues are captured and followed up as expected.
Original PR description
Steps to reproduce 1. Install quality 2. Create an incoming email server 3. Go to Quality > Configuration > Quality Teams > Team > add alias email 4. Do not fill the company field 5. Send email to this alias 6. Fetch emails from incoming email server Issue: - Record is not created in the quality alert Root cause: - For the Quality alert model, the field `company_id` is required, but while we fetch emails We haven't set the `company_id` on the quality alert team, resulting in trying to insert a null value on the quality alert model. Solution: - Give a default value to company_id. - Raise a validation error on not having a company_id - Update alias default values on changing company_id opw-5917791 Forward-Port-Of: odoo/enterprise#121778 Forward-Port-Of: odoo/enterprise#109947
This change keeps POS order totals and line quantities in sync when a table order is split and paid more than once. It prevents already-paid items from still appearing on the parent order, so cashiers cannot accidentally charge the same items again from the Orders tab.
Original PR description
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid…
In POS Restaurant with Germany Fiskaly enabled, splitting and paying from a table works once, but repeating the same flow from the Orders tab lets the parent order show lines that were already paid in previous splits. Functionally, the cashier can keep splitting and paying the same line again and again because the parent draft order is not updated consistently in that path. Steps to reproduce: ------------------- * Enable POS Restaurant with l10n_de Fiskaly * Create a table order (e.g. 3 meals + 3 drinks) * Open Split Bill, move 1 meal + 1 drink, and pay * From Orders tab, open the remaining parent order and repeat split + pay * Reopen the parent order from Orders tab > Observation: The parent order still contains quantities that were already split/paid, so the same items can be paid multiple times from the Orders tab. Why the fix: ------------ The Fiskaly `syncAllOrders` override diverged from core sync behavior in the split flow: it ignored explicit `options.orders` and did not await transaction creation for inactive transactions. In the split-bill path this could skip or desynchronize parent-order updates, leaving stale quantities on the parent order. The fix restores expected sync semantics by honoring `options.orders` and awaiting transaction creation before deciding sync eligibility. opw-6175880 Forward-Port-Of: odoo/enterprise#117206
4 changes
Enhancements to existing features
This pull request bundles several user-facing fixes and enhancements across accounting, planning, appointments, point of sale, maps, projects, and access to SaaS databases. It improves reporting accuracy, prevents duplicate POS preparation tickets, speeds up appointment availability checks, and makes planning and map views behave more predictably, which should reduce confusion and save time for end users.
Resolved issues and error corrections
This update fixes a problem in the barcode-based inventory workflow. It helps ensure users can complete stock operations more reliably when using barcode scanning, reducing interruptions during warehouse tasks.
This update makes rental products work properly with Click & Collect in the online shop. It uses the rental period to show the correct availability, improves the add-to-cart experience when items are unavailable, and reduces confusing warning messages for shoppers.
Original PR description
**Purpose:** - Click & Collect and Rental are not working together, the rental dates are not used to display the availability of the product. - Unmute rental period selector when out of stock - Display muted Add to Cart button when out of stock - Remove renting warning message - Select the first valide date when adding to cart from the shop page instead of showing an error message if the product is not available for the default date **Specification:** Create a new bridge module between website_sale_collect and website_sale_renting to ensure that we use the rental dates to compute the availability if this is a rental product. Task-6081690 See also: - https://github.com/odoo/odoo/pull/266874
This change fixes an issue that prevented PDF downloads for a specific type of Guatemala vendor bill. Users can now generate and download the document successfully after sending it to the tax authority.
Original PR description
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding…
**Steps to reproduce:** - Install the `l10n_gt_edi` module and switch to a `GT Company`. - Create a new vendor bill with: - Vendor: GT Company - GT Document Type: `FESP` - Add taxes `VAT Withholding 12%` and `ISR Withholding 5%` in Invoice lines. - `Confirm` the bill and `Send to SAT`. - From the gear icon, click `Download` > `PDF`. **Error1:** `KeyError: 'gran_total'` **Error2:** `KeyError: 'retencion_grand_total'` **Root Cause:** In commit [1], the code at [2] missed calling `_l10n_gt_edi_add_base_values()` before `_l10n_gt_edi_add_withholding_values()`. However, `_l10n_gt_edi_add_withholding_values()` uses the `gran_total` value, which is initialized by `_l10n_gt_edi_add_base_values()`, resulting in a `KeyError`. Additionally, the report template at [3] references `retencion_grand_total` instead of the correct key `retencion_gran_total`, causing another `KeyError`. **Fix:** This commit prevents errors and ensures users can successfully download the PDF by applying a fix similar to [4], [1]: https://github.com/odoo/enterprise/commit/44afd19e4ed0827e343af0e584c81e579935c9e8 [2]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L305-L328 [3]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/views/report_invoice.xml#L72 [4]: https://github.com/odoo/enterprise/blob/9846b337cfe1876017c7c2ce3041569d7a2ac03f/l10n_gt_edi/models/account_move.py#L790-L800 opw-6323049 Forward-Port-Of: odoo/enterprise#122030
5 changes
Enhancements to existing features
This update removes technical e-reporting fields from the standard invoice screen so regular invoicing users see a cleaner, less cluttered view. The relevant e-reporting flow, status, and any blocking issues are still available in the invoice chatter, with a direct link to the related flow when needed. It also stops showing address validation errors on B2C invoices when they are not required.
Original PR description
E-reporting technical fields were displayed directly on invoices, adding noise for regular invoicing users. Hide the e-reporting status columns and technical block from the standard invoice views. Log the relevant e-reporting flow, status and blocking errors in the invoice chatter instead, with a link to the related flow. Also avoid reporting address validation errors on B2C invoices, as they are not required for Flux 10 e-reporting. Task-6273226
This update alerts cashiers when a Point of Sale device clock is drifting from the server time. It helps prevent wrong order and payment timestamps, which can otherwise lead to mismatches in receipts and daily reports.
Original PR description
PoS timestamps (order creation, payment) are captured from the device clock to support offline sessions. When a device clock is misconfigured, all timestamps in that session are silently wrong, causing discrepancies in daily reports and receipts. opw-6320108 --- 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 prevents users from saving default values for fields they do not have permission to modify. It helps keep user settings aligned with access rights and avoids confusion or misuse of restricted fields.
Original PR description
Users should be able to set default values only for fields they have access to. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273089
This fix prevents spreadsheet data from breaking when a linked record uses a text ID instead of a numeric one. It improves reliability for reports and pivots involving those records, so users see correct results instead of import or display issues.
Original PR description
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
This update brings the spreadsheet component to a newer version and fixes a data handling issue that could affect pivot tables and account-related records. It helps spreadsheets display and process certain business data more reliably, especially when records use non-numeric identifiers.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/1a9c76131c [REL] 18.0.73 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/1a9c76131c [REL] 18.0.73 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/9512d92c70 [FIX] config: bump node version in GH action [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/5edfaee5e4 [IMP] pivot: give full dimension to pivot normaliser [Task: 6023622](https://www.odoo.com/odoo/2328/tasks/6023622) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
2 changes
Resolved issues and error corrections
This fix ensures that warning activities created when an orderpoint fails are recorded as coming from Odoo’s system user, not from the customer or portal user who triggered the operation. It prevents incorrect activity history and avoids access issues caused by customer IDs being stored in internal records.
Original PR description
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The…
When an orderpoint fails during a portal user's transaction (e.g., eCommerce checkout), the system catches the `Procurement Exception` and logs a warning activity on the product template. The exception handler uses `.sudo().activity_schedule()`, which bypasses the write access restriction but leaves `env.uid` as the portal user. Therefore, the restricted portal user permanently becomes the `create_uid` (Author) of the activity. System exception activities should always be authored by the system (OdooBot), never by a portal or public user. This context leak corrupts the activity metadata by injecting an external user ID into internal backend logs. Chain `.with_user(SUPERUSER_ID)` to the `.sudo()` call in `stock_orderpoint.py` when scheduling the exception activity. This ensures the environment context is stable and the activity is authored by OdooBot, which transcends multi-company record rules. Steps to Reproduce on Runbot/Fresh Database on version 17.0: 1. Enable Multi-Company with Company A and Company B. Set Company B as the active company for the website. 2. Restrict the main Admin (Runbot) user strictly to Company A. 3. Create a Shared Product (Company field left blank). 4. Set a Reordering Rule (Orderpoint) for the product that is guaranteed to fail routing. 5. Navigate to the frontend website and sign up as a new user (this creates a Portal User in Company B). 6. As the newly signed-up Portal User, complete an eCommerce checkout for the shared product. 7. The checkout succeeds, but the backend triggers the orderpoint failure and logs the exception activity on the product template. 8. Check the chatter for this product: the `create_uid` is incorrectly set to the Portal User instead of OdooBot (1). 9. (In 19.0 Upgrade) Log in as the Admin user (set strictly to view Company A), navigate to the product, and the AccessError for reading will appear due to this leaked id. [opw-6253978](https://www.odoo.com/odoo/my-support-tasks/6253978?debug=assets) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents Odoo from creating one extra recurring event when a Google Calendar series ends on a boundary day in time zones behind UTC. It keeps Odoo aligned with Google so users no longer see duplicate or unexpected events after syncing.
Original PR description
When Google sends a recurrence with UNTIL in UTC (UNTIL=...Z), users in timezones behind UTC can get one extra occurrence on the boundary day. Google's UNTIL represents the last allowed start in UTC, but that UTC date fell into the previous local day. Because Odoo was comparing event start times as naive local datetimes against a cutoff derived from the wrong date, the boundary occurrence passed the check and was created. Steps to reproduce: 1. Set the user's timezone to a UTC-negative offset (e.g. America/Argentina/Buenos_Aires, UTC-3). 2. In Google Calendar, create a weekly recurring event (e.g. every Thursday at 12:00 local). 3. Edit the series with "This and following events" so the old series ends with UNTIL set to 02:59:59 UTC of the next day (= 23:59:59 local of the last valid occurrence day). 4. Sync with Odoo -> an extra event is created on the day after the last valid Thursday, which does not exist in Google Calendar. opw-6024835