Tuesday, May 12, 2026
28 changes · saas-19.3
Enhancements to existing features
This update enhances the ZKTeco time clock integration by ensuring accurate time zone handling and improving the user interface. Specifically, it corrects timezone discrepancies for punch times and streamlines the process for managing ZKTeco transactions, leading to more reliable attendance tracking.
Original PR description
This commit includes the following: - Hide Transactions/Terminals menus until BioTime is configured; Test Connection now reloads the client so menus surface immediately. - Use upload_time (timezone-aware against the BioTime company tz) instead of punch_time, and convert through res.company.tz so punches land in UTC correctly. - Reset and flag linked ZKTeco transactions when their attendance is deleted; keep the guard against deleting processed-and-linked ones. - Replace the cog menu with Fetch / Process / Re-Fetch buttons in the list header, and allow editing punch_type when the fetched value was unsupported. Task-6181807
This update streamlines the process for canceling old invoices in Mexico's EDI system. When a new invoice replaces an older one, the system now automatically cancels the original invoice, eliminating a manual step for users. This improves efficiency and reduces potential errors related to invoice management.
Original PR description
Triggers the EDI document cancellation method for the substituted invoice when the substitute document is signed, removing the requirement for the user to go back and click cancel again as well as bypassing calling a wizard with no options for the user to select from. task-5927581 Forward-Port-Of: odoo/enterprise#107541
Resolved issues and error corrections
This update fixes an issue where the overtime indication on timesheets was incorrect for employees on flexible work schedules. The change adjusts how the system calculates working hours to accurately reflect actual time worked, particularly when using schedules with varying daily hours. This ensures accurate overtime reporting.
Original PR description
**problem:** On timesheets, the overtime indication next to an employee's name is incorrect when using flexible work schedules. for example: a "Flexible 20h" schedule (4h a day) shows 1h of negative…
**problem:** On timesheets, the overtime indication next to an employee's name is incorrect when using flexible work schedules. for example: a "Flexible 20h" schedule (4h a day) shows 1h of negative overtime even when the employee has logged exactly 20h for the week. **steps to reproduce:** 1. Create a new working schedule with flexible hours enabled for example (20h/week, 4h/day average) 2. Assign this schedule to an employee 3. Go to Timesheets, search for the employee 4. Navigate to a past week 5. Enter 4h on each working day 6. Observe the overtime indication shows incorrect value (-01:00) **cause:** In `resource/models/resource_calendar.py`, the flexible hours algorithm that determines the date range by converts UTC boundaries to the employee's timezone. When the employee's timezone has a positive UTC offset (UTC+1, like in brussels time zone), `Sun 23:59:59 UTC` becomes `Mon 00:59:59 CET`, pushing `end_date` to the next Monday. This creates an 8 day range instead of 7. The algorithm then starts a new weekly budget for the spillover day and allocates 1 extra hour, making `allocated_hours` 20.9999998 instead of 20. **fix:** - Use the UTC date before conversion to the employee's timezone when determining the flexible date range. - prefer `self` when it is the flexible calendar being queried, so hr_contract's `_get_calendar_at()` override cannot substitute the contract's calendar parameters (full_time_required_hours, hours_per_day) for the flexible ones. **note** Updating the test (`test_no_carried_over_leaves_for_flexible_resource`) in `hr_holidays/tests/test_expiring_leaves.py` expected duration logic, is to match the corrected inclusive day range and prevent asserting the previous spillover behavior. link to the enterprise PR: https://github.com/odoo/enterprise/pull/112879 link to the community PR: https://github.com/odoo/odoo/pull/257269 opw-5970511 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/enterprise#116320 Forward-Port-Of: odoo/enterprise#112879
This update fixes an issue where users could still edit protected folders within the company's main document area. The change ensures that editable forms are automatically set to read-only when a protected folder is accessed, maintaining data integrity and preventing unauthorized modifications. This resolves a potential risk of incorrect data being saved.
Original PR description
In odoo/enterprise#106192, we have modified the function userPermissionViewOnly that was preventing the user from editing document he cannot: we have removed the condition preventing user to edit…
In odoo/enterprise#106192, we have modified the function userPermissionViewOnly that was preventing the user from editing document he cannot: we have removed the condition preventing user to edit protected document (mainly folder at the company root). That was an error as even if the user has "edit" access (which is ensured in that method), the document can still be protected and the form to edit it should be in readonly then. We ensure here that the form in the details panel is in readonly in that case. How to reproduce: - log as demo and go to Document - Click on Inbox folder - Open details panel - Change for example the contact of the document You get an error while you shouldn't be able to edit it (as the folder is protected). Technical note: we re-add the condition in the method userPermissionViewOnly: (!this.documentService.userIsDocumentManager && this.record.data?.user_folder_id === "COMPANY") that we slightly modify to limit the protected document to folder only: (!this.documentService.userIsDocumentManager && this.record.data?.user_folder_id === "COMPANY" && this.record.data?.type === "folder") Task-5881531 Forward-Port-Of: odoo/enterprise#116709
This update resolves an issue where newly created analytic distribution records would disappear after a page reload. The fix ensures the widget's data is properly synchronized with the database, preventing data loss when updating distribution settings. This improves data reliability and reduces the risk of lost configurations.
Original PR description
Steps to reproduce 1. Go to Accounting → Configuration → Analytic Distribution Models 2. Create a new model, name it, and in the distribution column pick an analytic account 3. Click outside the row…
Steps to reproduce 1. Go to Accounting → Configuration → Analytic Distribution Models 2. Create a new model, name it, and in the distribution column pick an analytic account 3. Click outside the row and reload the page Issue The newly created record vanishes because `web_save` received `analytic_distribution: false`. The single click that closes the popover also triggers the editable list's `leaveEditMode`, which calls `record.save()`. That save runs before the widget has flushed the user's pick into `record.data`, so the write goes out with stale/empty data. This became reliably reproducible after [37d78a47bb20], which moved the list renderer's outside-click listener from `document` (bubble) to `window` (capture). Because the list is mounted before the widget, its capture-phase listener now fires first: `leaveEditMode` → `record.save()` is already in flight by the time the widget's own window click handler runs, so the widget's commit loses the race. Solution `record.save()` awaits `_askChanges()` before writing: https://github.com/odoo/odoo/blob/cdf8aaec82ee387c8f29b8327efbc95fd17e2cb8/addons/web/static/src/model/relational_model/record.js#L268-L271 `_askChanges()` triggers `NEED_LOCAL_CHANGES` on the model bus and awaits any proms handlers push onto it: https://github.com/odoo/odoo/blob/cdf8aaec82ee387c8f29b8327efbc95fd17e2cb8/addons/web/static/src/model/relational_model/relational_model.js#L249-L253 This is the framework's standard hook for widgets that hold uncommitted local state; `ace_field` and `domain_field` already use it. Subscribe the analytic distribution widget to the same event and, when the dropdown is open, push a `commitChanges()` prom that awaits the existing `save()`. Because `record.save()` awaits these proms before running `_save`, the widget's pending distribution is guaranteed to be on `record.data` by the time the write payload is built, regardless of click-listener ordering. opw-6106309 Forward-Port-Of: odoo/odoo#260421
A recent update caused the onboarding plan wizard to open without displaying the expected plan badges. This issue stemmed from a change that removed crucial context information. This fix restores the correct display of badges, ensuring users see all available onboarding plans as intended.
Original PR description
Steps to reproduce: 1- Install Employees app 2- Open the app and select any employee 3- In the chatter, click the onboarding plan link Issue: Starting from version 18.4 and onwards, clicking the link opens the 'Launch Plan' wizard without the Offboarding/Onboarding plans Expected behavior: The wizard should contain the plan Badges just like in previous versions or when clicking the 'Activity' button in the chatter Why this happens: One of the changes in the commit ef34950 was removing the following line: `context.params = state` The `state` included the `active_model` value which was passed in the url. As a result, `res_model` attribute in the model 'mail_activity_schedule' is `false`. The `_compute_plan_available_ids` will then return an empty list. So the consequent call which gets the available plans to display as a Badge will not be made. opw-6074918 Forward-Port-Of: odoo/odoo#258349
This update fixes an issue where changing the delivery date for Hungarian invoices incorrectly recalculated journal entries, leading to financial discrepancies. The fix ensures that the correct exchange rate is applied when the delivery date is modified, maintaining accurate accounting records. This improves the reliability of financial reporting for Hungarian transactions.
Original PR description
### Issue: When changing the delivery date (used as the Hungarian exchange rate date), some journal lines could be recomputed incorrectly, leading to unbalanced entries ### Cause:…
### Issue: When changing the delivery date (used as the Hungarian exchange rate date), some journal lines could be recomputed incorrectly, leading to unbalanced entries ### Cause: `expected_currency_rate` was recomputed when `delivery_date` changed, but the new value was never automatically applied In addition, after https://github.com/odoo/odoo/pull/225407, `_sync_tax_lines` partially updated the lines: https://github.com/odoo/odoo/blob/f5501e5c8dcf60444077912db4c87e7a3f2654a6/addons/account/models/account_move.py#L3029-L3031 https://github.com/odoo/odoo/blob/f5501e5c8dcf60444077912db4c87e7a3f2654a6/addons/account/models/account_move.py#L1633-L1637 These methods reapply the previous tax rate, causing base and tax lines to be updated inconsistently As a result, when the base amount increases, the tax amount decreases, and vice versa ### Steps to reproduce: - Install `l10n_hu_edi` and `accountant` with demo data, then switch to the `HU company` - Go to Currencies → USD and add two rates: April 5: HUF per Unit = 100 April 6: HUF per Unit = 150 - Create an Invoice: (Any customer, Currency: USD, Line: Price = 1000, Tax = 27%) - Open the Journal Items and duplicate the browser tab for comparison - In the duplicated tab, change the Delivery Date to April 5 and save - Change the Delivery Date back to today and compare both tabs ### Before the fix: The values differ between both tabs because the tax lines keeps the old exchange rate opw-5801126 Forward-Port-Of: odoo/odoo#263694 Forward-Port-Of: odoo/odoo#258310
This update fixes a bug in the bank reconciliation process that prevented users from correctly selecting multiple lines for actions. The change ensures accurate filtering and comparison of related records, improving the reliability of this key financial function. This resolves an issue where the system wasn't properly handling multiple selections.
Original PR description
In this commit: https://github.com/odoo/enterprise/commit/fa8fedc4e2501a273e7f8f3f7f4462b2b58907b9 We introduce a way for user to select multiple lines and perform an action out of it. In the dropdown, there should be an intersection of all reco model of the selected lines but it wasn't working properly in two cases: - When only one selected lines, remainingRecoModels was empty and the filter was filtering everything, added a early return for that - When multiple lines, we compare the first list of reco model with all the others but we compare object which is not working in js. Now we will compare the id. no task id Forward-Port-Of: odoo/enterprise#115770
This update resolves an error in the FAIA report XML export for Luxembourg customers. The issue stemmed from a missing 'TVA' TaxType element, as required by Luxembourg tax regulations. This fix ensures accurate report generation and compliance.
Original PR description
This is one of several commits fixing the FAIA xml export. The customer in ticket [opw-5427296](https://www.odoo.com/odoo/unassigned-tasks/5427296) received several errors which mention that the `TaxType` element should be 'TVA'. This is corroborated by one of these elements in the XSD files for the FAIA report. The XSD files can be found at the link below. https://pfi.public.lu/dam-assets/backup/FAIA/FAIA/XSD_Files.zip opw-6118272 [link](https://www.odoo.com/odoo/project.task/6118272) *For future techs or functional support agents: updating `l10n_lu_reports` may not automatically apply the fix. You may need to go to the relevant Views model and select ⚙️ > Compare/Reset, then Hard Reset.* Forward-Port-Of: odoo/enterprise#116344 Forward-Port-Of: odoo/enterprise#113720
This update fixes an issue where users were incorrectly directed to a standard form view when opening documents linked through Studio. Now, when accessing documents from Many2One fields, the system opens the appropriate Kanban or List view, allowing users to directly preview and navigate the document content.
Original PR description
Problem: When opening a linked `documents.document` record from a Many2One field added via Studio, the user is redirected to the standard form view. This is problematic because the form view does not allow the user to preview the actual document or navigate into it if the record is a folder. Solution: override `get_formview_action` to open the Kanban/List/Activity views. task-6068437 Forward-Port-Of: odoo/enterprise#116675 Forward-Port-Of: odoo/enterprise#113149
This update resolves an issue where the correct fiscal position (Domestic) wasn't being applied for sales within the EU. The change ensures that VAT prefixes are properly considered, leading to accurate sales reporting and compliance with VAT regulations, particularly for intra-EU B2B transactions. This fix impacts how VAT is calculated and processed for sales orders.
Original PR description
With l10n_nl: - Set the fiscal positions in this order: 1. Domestic 2. EU Intra B2B - Create a contact with: - German address - Dutch delivery address - Dutch VAT - Create a second contact with: - German address - Dutch delivery address - No VAT - Create a Sales Order for each contact: - For the first contact, the applied fiscal position is EU Intra B2B - For the second contact, the applied fiscal position is Domestic The detected fiscal position should be Domestic in both cases In _get_fiscal_position vat_exclusion is computed using the VAT prefix of the partner and our company. But if the prefix of the VAT does not match the country of the partner, it's delivery address will still be overriden. opw-5892138 Forward-Port-Of: odoo/odoo#258899
This update fixes an issue where purchase order lines didn't correctly display the associated analytic distribution when a project was assigned. The fix ensures that the product's original analytic distribution, along with the project's, is consistently shown on new order lines. This improves accuracy in tracking costs by project.
Original PR description
__ ## Short functional explanation of the error When creating a Purchase Order. We add a line containing a product that has an analytic distribution. After setting a project on this PO, when we add…
__ ## Short functional explanation of the error When creating a Purchase Order. We add a line containing a product that has an analytic distribution. After setting a project on this PO, when we add another line containing the same product, the analytic distribution of the product isn't added anymore, only leaving it with the analytic distribution of the project. ## Reproduction Steps 1. Go to settings and enable Analytic Accounting. 2. Go to Accounting > Configuration > Analytic Distribution model. Create a model with a product (prd) you remember, and add an analytic distribution (ad). 3. Go to Project. On a given project (p), select the Hamburger menu and click Settings. Then, in the Settings tab, under Analytic, make sure the Project field is filled. 4. Create a new Purchase Order. Select a vendor and add a line with the product (prd). On the top right of the Form, click on the view button and select Analytic Distribution to show it on the form. There, we should see the product (prd) with its corresponding Analytic Distribution (ad) on the form. 5. Click on the Other Information tab and select the project (p). Click on the Product tab. There, under Analytic Distribution field, you should see (ad) and the Analytic Distribution of the project (p). 6. Click on save and add another line with the exact same product. ### Expected behavior Under Analytic Distribution, we should see (ad) and the Analytic Distribution of the project (p), as for the first order line ### Unexpected behavior Under Analytic Distribution, we only see the Analytic Distribution of the project (p). ## Origin of the issue When we add another line, we trigger the compute method of the Analytic Distribution. However, due to this piece of code: https://github.com/odoo/odoo/blob/eed303b9926062eb71be6cf8dc95165efc413ed8/addons/project_purchase/models/purchase_order_line.py#L14 when we create a new order line, we never compute its analytic distribution: `self` will contain only `project_lines`, and `empty_project_lines` is empty as well. Therefore, we call the super method with nothing, so when we get in the super method: https://github.com/odoo/odoo/blob/eed303b9926062eb71be6cf8dc95165efc413ed8/addons/purchase/models/purchase_order_line.py#L249-L259 we never compute the analytic distribution of the newly created line. This piece of code was added in this commit: https://github.com/odoo/odoo/commit/c1ea8446259bd3338c004e88d48ad77ded7ef2ae to fix the issue that when a user enters manually an analytic distribution, this entry will be lost when triggering the compute of the analytic distribution. However, due to the agency of the code, we cannot prevent losing *both* manually added analytic distributions and product analytic distribution. After consulting the product owner, we concluded that there was no perfect solution in this case, but we'd rather keep the product analytic distribution, as it is much harder to add it again after its removal. Therefore, this commit reverts the previously mentioned commit, while keeping the refactor it introduced. __ opw-6063418 Forward-Port-Of: odoo/odoo#257558
This update significantly reduces memory usage during the installation of the stock account module, particularly in large databases. By disabling prefetching, the module now uses 55% less memory, preventing potential performance issues. The change resulted in a slight (10%) increase in installation time, which is considered an acceptable tradeoff.
Original PR description
## The Problem During the initialization of `stock_account`, the logic creating `product.value` instances triggered cache misses on `product.product`, accessing fields (`company_id` and…
## The Problem During the initialization of `stock_account`, the logic creating `product.value` instances triggered cache misses on `product.product`, accessing fields (`company_id` and `standard_price`) inside `_create_product_value`, and field `uom_id` inside `_run_fifo_get_stack`. Due to prefetching, this loaded all product data into memory, causing significant memory usage on large databases. ## The Solution Disabled prefetching in the full flow. Didn't go with fetching only the needed fields instead of disabling for two main reasons: - Field `standard_price` accessed in the loop is company dependent, so it needs to be fetched inside, which would be a bit verbose. - Fetching `company_id` outside the loop, `standard_price` inside the loop, and `uom_id` which is accessed down the stack in the `.create` call on `product.value` won't be an explicit/robust solution for the long term. --- ## Benchmarks *Tested on a SaaS database with 500k products:* | | Before | After | Note | | :--- | :--- | :--- | :--- | | **Memory** | 3.6GB | 1.6GB | **-55%** (fits in memory limit) | | **Time** | 10m | 11m | **+10%** (acceptable tradeoff) | **OPW-6173153** Forward-Port-Of: odoo/odoo#262702
This change corrects a bug where the gross salary line was missing from the salary configurator when the user interface was set to a non-English language (like French). The fix ensures that the gross salary is always displayed, regardless of the selected language, by updating how the system generates salary categories.
Original PR description
**Problem:** On a Belgian company with the UI set to French (or any non English language), the gross line never appears in the salary configurator sidebar when opening an offer. **Steps to…
**Problem:**
On a Belgian company with the UI set to French (or any non English language), the gross line never appears in the salary configurator sidebar when opening an offer.
**Steps to reproduce:**
1. Create a Belgian company.
2. Install French and set the admin user to French.
3. Go to an applicant (e.g Laurie Poiret), create a salary offer, save.
4. Open the offer link (salary configurator).
**Cause:**
The base `_get_compute_results` uses the translated `category_id.name` ("Salaire mensuel" in french) as the dictionary key when writing entries into `resume_lines_mapped`. The payroll override function `_get_period_name`, which for monthly schedules returned the hard coded english string `"Monthly Salary"` instead of the translated category name. This caused a key mismatch: the gross line was stored under the translated key, while the override rebuilt `resume_categories` with the english key so when the template iterates over categories and looks up `lines[category]`, the whole "Monthly Salary" bucket was invisible in every non english language.
**Solution:**
We should now return the `category_id.name` directly (the translated name coming from the record itself). This keeps all keys consistent between `resume_categories` and `resume_lines_mapped` regardless of the language used.
also because in https://github.com/odoo/enterprise/blob/1845042ff388593c4cdf547d47c018f42bd02c7c/l10n_be_hr_contract_salary/controllers/main.py#L450
We use `resume = result['resume_lines_mapped']['Monthly Salary']`
We need to re-design this by using the actual translated names, and building `result` keys based on the language selected (the same should be applied for "Yearly benefits").
opw-6009711
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/enterprise#116657
Forward-Port-Of: odoo/enterprise#110676This update fixes an issue where partners sharing the same VAT number but with individual turnovers below €250 were incorrectly excluded from VAT reports. The change groups partners by VAT number and includes them in the report if their combined turnover exceeds the threshold, ensuring accurate reporting for Belgian businesses.
Original PR description
When having different partners with the same vat number and their individual turnover values are less than the threshold they were not included in the partner vat listing report even though if the total turnover for their vat number is above the threshold. This commit handles this case by grouping by vat number and if the total turnover for a vat number is above the threshold then it will be shown in the report with another level beneath it to show the partners having this vat number even if their individual turnovers are below the threshold. task-6133010 Forward-Port-Of: odoo/enterprise#116495 Forward-Port-Of: odoo/enterprise#115251
This update resolves an error that occurred when users attempted to mark payslips as paid, specifically when the 'Include Unpaid' option was enabled. The change ensures that the system correctly handles unpaid payslips during this process, preventing a technical error and improving the reliability of the payroll reporting feature.
Original PR description
Currently, an error occurs when a user attempts to mark a payslip as paid. **Steps to Reproduce:** - Install the `hr_payroll` module without demo data. - Go to `Payslips` and click on `New…
Currently, an error occurs when a user attempts to mark a payslip as paid. **Steps to Reproduce:** - Install the `hr_payroll` module without demo data. - Go to `Payslips` and click on `New Off-cycle`. - Create a record > `Compute` > `Validate`, and Pay. - In the wizard, enable `Include Unpaid` and select `CSV` mode. - Click `Mark as Paid`. **Error:** `UnboundLocalError: cannot access local variable 'rows' where it is not associated with a value` The error occurs when a user tries to mark a payslip as paid with Include Unpaid enabled. When the wizard is created from here [1], the default unpaid payslips are empty. In this case, the system assigns an empty set of payslips to process [2].and the rows variable is not defined because there are no payslips to work on, which raises the error [3]. This commit ensures that when the wizard is created, the matched unpaid payslips are passed to the wizard. If the Include Unpaid option is enabled, the unpaid payslips are assigned for processing, similar to [4]. The unpaid payslips cannot be empty, as they always include the currently processed payslip. Also, the rows are redefined for each payslip case and updated accordingly. Therefore, this commit ensures that the rows are created at the end from grouped payments. [1] https://github.com/odoo/enterprise/blob/a784d118e076724b02e5c59d9ce5d1815c42b0bf/hr_payroll/models/hr_payslip.py#L792-L809 [2] https://github.com/odoo/enterprise/blob/e971fca0d09e564ae9029f3d7e166e078c44dcbb/hr_payroll/wizard/hr_payroll_payment_report_wizard.py#L56 [3] https://github.com/odoo/enterprise/blob/e971fca0d09e564ae9029f3d7e166e078c44dcbb/hr_payroll/wizard/hr_payroll_payment_report_wizard.py#L97 [4]: https://github.com/odoo/enterprise/blob/a784d118e076724b02e5c59d9ce5d1815c42b0bf/hr_payroll/models/hr_payslip_run.py#L274-L288 sentry-7436885639 Forward-Port-Of: odoo/enterprise#115090
This update fixes an issue where currency rates were incorrectly calculated for VAT reports. Previously, the system used any invoice line, even non-product lines, leading to inaccurate rates. Now, the system prioritizes the first actual product line to ensure correct rate derivation, improving the reliability of VAT reporting.
Original PR description
The currency rate was previously computed using the first invoice line, regardless of its type. This caused incorrect rate calculation when the first line was not a product line (e.g., section, note, or display-only lines). This fix filters invoice_line_ids to use the first actual product line when extracting amount_currency and balance, ensuring that the derived rate reflects a valid monetary line. opw-5208724 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#239920 Forward-Port-Of: odoo/odoo#237535
This update resolves an issue where the 'Add a line' button was unresponsive at the top of mobile grid views (like Timesheets). The fix adjusts how elements are sized on smaller screens, ensuring the button is always clickable. This improves the user experience for mobile users.
Original PR description
**Steps to reproduce** On mobile: - Open a grid view (e.g. Timesheets > All timesheets) - Try to click on "Add a line" for the first employee - Issue: nothing happens. Notice that by scrolling down the list to employees at the bottom, it becomes possible to click on "Add a line". **Cause** `o_grid_cell_overlay` elements (with `h-100`) were taking more than the expected height in mobile, because the `o_grid_section_title` divs only have `position: sticky` on larger viewports. With the default `position: static`, the child element's height was exceeding its parent's height. opw-5853489 Forward-Port-Of: odoo/enterprise#113400
This update resolves a bug that prevented QR codes from being generated correctly during batch invoice sending. Previously, the QR code was calculated for all invoices before the signature was applied, resulting in an empty QR code. Now, the QR code is only generated for each invoice during the batch sending process, ensuring accurate signature application.
Original PR description
Description of the issue/feature this PR addresses: in this PR we aim to fix a bug where the l10n_sa_qr_code_str is not getting computed correctly when batch sending due to the qr_code being prematurely computed and cached before the invoice gets the signature filled. Current behavior before PR: Before this PR when batch sending the qr code was being computed for all the invoices being batch sent before each invoice runs _l10n_sa_generate_unsigned_data to set l10n_sa_invoice_signature which leads to an empty qr code. Desired behavior after PR is merged: after this PR we only compute the qr code for each invoice during sending which ensures that l10n_sa_invoice_signature was set. task-6164686 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves an issue where setting a maximum package weight in Sendcloud prevented accurate shipping rate calculations. The fix ensures that package splitting is handled correctly, allowing rates to be generated accurately even when package weights exceed the maximum deliverable weight. This improves the reliability of shipping cost estimations.
Original PR description
Issue ----- Putting a max weight on a package type causes getting a rate with Sendcloud to fail. Steps to reproduce ----- - Setup Mondial Relay using Sendcloud - Set a default package type with max…
Issue ----- Putting a max weight on a package type causes getting a rate with Sendcloud to fail. Steps to reproduce ----- - Setup Mondial Relay using Sendcloud - Set a default package type with max weight 2kg - Create a product with a 500g weight - Create a SO with the product - Add delivery - Sendcloud Mondial Relay - Get rate > Impossible to get a rate Cause ----- When retrieving the shipping method to use when retrieving a rate, we use the real weight of the order. https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L67 https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L81 However, when making the rate call, we use the value returned by `_split_shipping` https://github.com/odoo/enterprise/blob/cca1433f5a064673b8e007530e20e8a9fe72949b/delivery_sendcloud/models/sendcloud_service.py#L91 which is equal to the maximum weight of the package. This is blocking in some cases, like if - the real weight is 750g - the package max is 2kg - Sendcloud returns a shipping method for [500g;1kg] Asking a rate for this method & a 2kg package will fail (rightfully so). Solution ----- The shipment should be split into packages before retrieving the shipping methods. Otherwise the problem might be the other way around where we retrieve a shipping method for the whole order, only to split it into multiple packages because they don't fit in one. Also, the `shipping_weight` returned by `_split_shipping` should only be different from the order's total weight if it is higher than the maximum deliverable weight. ----- Ticket: opw-5947199 Forward-Port-Of: odoo/enterprise#116415 Forward-Port-Of: odoo/enterprise#108315
This update fixes an issue where purchase orders merged with related sale orders didn't correctly link all associated sales. The change ensures that all linked sale orders are properly connected during the merge process, improving data accuracy and streamlining the purchasing workflow. This resolves a previous bug impacting order tracking and reporting.
Original PR description
### Steps to reproduce: - In the settings Enable: "Multi-Steps Routes" - Unarchive the MTO route - Create a storable product with MTO enabled and a set vendor - Create and confirm two sale orders for…
### Steps to reproduce: - In the settings Enable: "Multi-Steps Routes" - Unarchive the MTO route - Create a storable product with MTO enabled and a set vendor - Create and confirm two sale orders for 1 unit of that product - Go to the purchase order view, select both PO > Actions > Merge RFQs #### > The un-cancelled Purchase order is only linked to one of the 2 SOs ### Cause of the issue: The sale orders linked to a PO in this flow are linked through the stock references: https://github.com/odoo/odoo/blob/fb79136e259e2b56746afda64b2536bddf6755c0/addons/sale_purchase/models/purchase_order.py#L60-L61 https://github.com/odoo/odoo/blob/fb79136e259e2b56746afda64b2536bddf6755c0/addons/sale_purchase_stock/models/purchase_order.py#L14-L15 However, the references of the PO merged to the present one are not merged as well. opw-6150636 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263371 Forward-Port-Of: odoo/odoo#261578
A bug causing spreadsheet image insertion requests to hang and crash due to excessive data loading has been resolved. The fix bypasses the database security filtering process, reducing the amount of data loaded into memory and preventing performance issues with large attachments.
Original PR description
To reproduce: ============= - In a db with a large amount of attachments - Insert an image in a spreadsheet - Observe the request hanging then ending with an error Problem: ======== - `ir.attachment._search` is overridden to apply security rules by building a domain based on public, `res_model`, `res_id` and `create_uid` fields - When no `res_model` restriction is present, the fallback path ORs in `res_model != False`, which matches nearly every attachment in the database - All matching records are then loaded into memory for Python-side access filtering via `_filtered_access`, causing the request to time out and crash with a memory error Solution: ========= - Set `bypass_search_access=True` on the many2many field definition so the ORM skips the `_search` override and relies on the SQL join to restrict returned records opw-6152979 Forward-Port-Of: odoo/enterprise#115766
This update resolves an issue where the table number on the kitchen display was being cut off when the order title exceeded a certain length. This prevented kitchen staff from quickly identifying the correct table for an order, leading to potential delays. The fix ensures the table number is always visible, improving kitchen efficiency.
Original PR description
**Steps to reproduce:** - Download the German language - Set the restaurant to QR + Ordering - Set the Service at Table, pay after each order - Set the language to German - Go to the Self and order…
**Steps to reproduce:** - Download the German language - Set the restaurant to QR + Ordering - Set the Service at Table, pay after each order - Set the language to German - Go to the Self and order something while the language is German - Chose table 12 - Go to the kitchen display - The title is truncated, meaning we can't see the table number **Why the fix:** If the title is more than 150px it will be truncated and "..." will replace the table number. This has been introduced in ed5b010dc7b5c11bbbc8513c1edb0ec4f58778c1 but not being able to see the table number might be bad as some people would need to spend time trying to figure out which table the order is for, instead of just having to look at the kitchen display. We now revert this change to break to a new line in the case where the card title is too long, so we can always see the table number. Before: <img width="317" height="156" alt="image" src="https://github.com/user-attachments/assets/25e76026-bdad-4639-9dfc-0d75ffa8d8c8" /> Afer: <img width="329" height="174" alt="image" src="https://github.com/user-attachments/assets/f387dd5f-96d3-4148-bc76-215393c76e67" /> opw-6096111 Forward-Port-Of: odoo/enterprise#114859
This update resolves an issue preventing the barcode app from accurately scanning pack-in-pack inventory counts. The fix ensures that the system correctly identifies and updates quantities when scanning nested packages, improving inventory accuracy. This enhancement directly addresses a reported problem during physical inventory counts.
Original PR description
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent…
### Steps to reproduce: - In the settings enable "Packages" - Create a storable product A and put 1 unit in a package P in stock - Inventory > Products > Packages > open your package P - Set a parent package PP as container - Inventory > Operations > Adjustments > Physical Inventory - Select you product line for A > Request a count (from the control panel button) - Enable Show Expected Quantity and confirm - Go to the barcode app > Count Inventory (1) - scan your parent package PP #### > traceback: Uncaught Promise > Cannot create property 'inventory_quantity' on boolean 'false' ### Cause of the issue: When the Package scan is processed, we loop over all quants related to it: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L566-L569 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L602-L617 And for each of these we try to find an existing line representing the quant to update or we do create a new line. Now, the issue, is that the subpackages of the quant are not provided to find the quant candidate line to update. As such, no line is found we enter the else clause and try to createa a NewLine: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L617-L627 This time however, the appropriate subpackage (the one of the quant) is provided to the arguments. And, since the line representing this quant is already existing, the `_createNewLine` will return False: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L393-L399 https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L423 This leads to a traceback at the end of the else close since `false.inventory_quantity` doe not make sense (Cannot create property 'inventory_quantity' on boolean 'false') https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_quant_model.js#L626-L627 Fix: We adapt the `_processPackage` of the `BarcodeQuantModel` to mimic the existing 'update' behavior on the `BarcodePickingModel`: https://github.com/odoo/enterprise/blob/30a28e28f8dd27cf2c88df65e5ff47eab59360c7/stock_barcode/static/src/models/barcode_picking_model.js#L2110-L2133 Note that UOM converstion should not be required since quants are already uniformly expressed in the product uom: https://github.com/odoo/odoo/blob/30b4edace6b0859cb1b1ba4f7f2ea80ba5398e3d/addons/stock/models/stock_quant.py#L52-L54 opw-5864591 Forward-Port-Of: odoo/enterprise#116715
This update fixes an issue where credit notes related to returned stock weren't accurately calculating the cost of goods sold (COGS). The fix ensures that the correct price unit (either from the original invoice or the returned stock movement) is used, regardless of how the credit note was created, leading to accurate financial reporting. This impacts inventory valuation and reporting accuracy.
Original PR description
**Steps to reproduce:** Problem A) - create a storable product avco perpetual - add 2 unit in stock and set a cost of 10 - set the invoicing policy as "delivered quantities" - create and confirm a SO…
**Steps to reproduce:** Problem A) - create a storable product avco perpetual - add 2 unit in stock and set a cost of 10 - set the invoicing policy as "delivered quantities" - create and confirm a SO for 2 quantities - validate the delivery - click on "Create Invoice" and confirm the invoice - from the delivery, create and validate a return for 1 unit. - from the product form, change the cost to 15 - from the sale order, click on "Create Invoice" - confirm the Credit Note Problem B) - create a storable product with fifo perpetual - confirm a PO for 1 unit at 10 and validate receive - confirm a PO for 1 unit at 20 and validate receive - confirm a PO for 1 unit at 60 and validate receive - create a SO for 3 unit - deliver 1 unit with backorder - deliver another unit with backorder - deliver the last unit - create and confirm invoice - return the second delivery - from the invoice click on 'credit note' and validate the credit note with a quantity of 1 **Current behavior:** Problem A) the cogs is 25 Problem B) the cogs is 30 **Expected behavior:** Problem A) it should be 10 Problem B) the cogs should be 20 cause the move returned had a value of 20 **Cause of the issue:** Inside \_get\_cogs_value(), if there is an original invoice linked to the credit note we take the unit_price from this invoice. But, if the credit note is not created from the invoice (via the Credit Note button) but via the sale order (via create invoices), the account\_move has no reverse\_entry_id so we won't use the price_unit from the original line. https://github.com/odoo/odoo/blob/686a0cf67bb1e818baf43309fc94f3f0462097ed/addons/stock_account/models/account_move_line.py#L56-L58 So basically what we do for now is: If the credit note was created from invoice we use the unit price from original invoice in all cases. If the credit note was created from sale order we use get\_price\_unit in all cases (which will work for fifo because we'll use the value of the returned move but fail for avco if the standard price has changed cause we use the standard price) https://github.com/odoo/odoo/blob/dccd2256660b1e211707b740074f5fbba95ae149/addons/stock_account/models/stock_move.py#L261-L265 **Fix:** Regardless of how the credit note is created, if it's fifo we use get\_price\_unit to adapt to the value of the moves, if not we use the unit_price from original invoice opw-6097090 Forward-Port-Of: odoo/odoo#259630
This update ensures that delivery orders are created correctly when sales orders are cancelled and then settled through the Point of Sale (PoS) system. Previously, products marked as 'delivered' remained on the sale order even when the delivery order was empty. This fix resolves an issue where PoS settlements were not properly reflected in the delivery process, leading to inaccurate inventory tracking.
Original PR description
Steps to reproduce ------------------ 1. Create a sale order with 2 products, confirm it 2. Cancel the SO, then click "Set to Quotation" 3. Open PoS, settle the order and pay 4. Check the delivery…
Steps to reproduce ------------------ 1. Create a sale order with 2 products, confirm it 2. Cancel the SO, then click "Set to Quotation" 3. Open PoS, settle the order and pay 4. Check the delivery order linked to the PoS order The delivery is empty, yet the products still show as "delivered" on the sale order. Why it's happening ------------------ When the SO is cancelled, its moves go to 'cancel' state. After resetting to quotation, those moves stay cancelled. When PoS creates the delivery, the filter in `_create_move_from_pos_order_lines` checks `has_valued_move_ids()` which returns False (all moves are cancelled), and `not move_ids` is also False (cancelled moves still exist). So the lines coming from the SO are excluded from the delivery. The fix ------- We now also create deliveries for lines whose SO moves are all cancelled. These are lines coming from a cancelled SO that now need to be shipped after we have settled their order from PoS. Note ---- The commit c0f338711f028088c98ea459f27c1669b29738d7 fixes this starting from saas-18.2, by introducing a separate `pos_repair` module which simplifies the main `pos_sale` code. In 18.2+, only the test will be forward ported. opw-6055856 Forward-Port-Of: odoo/odoo#263917 Forward-Port-Of: odoo/odoo#256693
This update resolves a bug that caused Purchase Orders to fail when the requested quantity was less than the vendor's minimum order quantity. The fix ensures a valid supplier is always selected, preventing crashes and allowing PO lines to be updated correctly, even with small orders.
Original PR description
FIX] purchase_stock: handle missing seller during PO line update (min_qty) **Steps to Reproduce:** - Install Sale, Inventory, Manufacturing, and Purchase. - Enable MTO, Units of Measure, and Routes.…
FIX] purchase_stock: handle missing seller during PO line update (min_qty)
**Steps to Reproduce:**
- Install Sale, Inventory, Manufacturing, and Purchase.
- Enable MTO, Units of Measure, and Routes.
- Create a product:
Set a vendor price with min_qty = 1.0.
Enable MTO route.
Add a BoM with a component product.
Set quantity to 0.1 (less than vendor min_qty).
- Create a Sale Order with the same product added twice.
- Confirm the Sale Order.
**Issue:**
During procurement:
- First procurement correctly fetches the supplier.
- On PO line update (_update_purchase_order_line), seller is recomputed.
Due to min_qty filtering, no seller is returned when quantity is low.
This results in: Missing seller, Missing product_uom, Invalid price
computation, And finally causes a crash when confirming the Purchase Order,
in _get_stock_move_price_unit: ZeroDivisionErroR
Root Cause:
- _select_seller filters suppliers using min_qty.
During merge/update flow, recomputed quantity may not satisfy min_qty.
Existing valid supplier (from initial procurement) is ignored.
No fallback handling in _update_purchase_order_line.
**Solution:**
- Add fallback logic when _select_seller returns no result: Use
_prepare_sellers() to fetch a valid supplier ignoring min_qty.
- Ensure a supplier is always available for: UoM resolution, Price computation
Prevents crash and ensures consistent PO line updates.
**Result:**
- No traceback when quantity < vendor min_qty
Supplier, UoM, and price are properly set
**OPW-6106487**
Forward-Port-Of: odoo/odoo#263699
Forward-Port-Of: odoo/odoo#259894This update resolves a problem where invoices created from timesheeted sales orders weren't correctly calculating the invoiceable quantities. The fix ensures that invoiceable lines are recomputed every time an invoice is created, regardless of whether dates are provided, leading to accurate invoicing for service-based products.
Original PR description
Steps --------- 1. Install Accounting, Sale and Timesheet 2. Create 2 product a. Product A - storable - invoiced on Ordered Quantity b. Product B - service - create a task on order - invoice on…
Steps
---------
1. Install Accounting, Sale and Timesheet
2. Create 2 product
a. Product A - storable - invoiced on Ordered Quantity
b. Product B - service - create a task on order - invoice on
timesheeted
3. Create an SO with 3 product A and 3 product B
4. Add a timesheet line for 1 hour of product A - can be done thanks to
the button appearing on the SO at confirmation
5. Create Invoice
6. Don't add dates to the wizard and confirm -> Both product appear
7. Add date range that do NOT include the timesheeted lines -> Only the
storable product appear
8. Repeat step 6 -> Only the storable product appear
Problem
---------
During the creation of the invoice, the invoiceable lines would get
computed dates where provided to the wizard
(`sale.order.line.qty_to_invoice`). When no dates were provided, we
would not manually trigger the invoiceable lines recomputation and were
relying one the data store in cache.
Solution
---------
Force the invoiceable quantity recomputation upon each invoice creation.
opw-6001094
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#261062