Daily updates from Odoo
Navigate
Branch
Wednesday, April 22, 2026
294 changes
2 changes
Miscellaneous changes
This pull request updates the saas-19.3 release branch with release-related maintenance changes. It helps keep the versioning and release information aligned for the current delivery cycle.
This pull request updates the Enterprise branch for the 19.3 release line. It is mainly a release-management change to keep the codebase aligned with the latest approved version and support ongoing maintenance.
19 changes
Enhancements to existing features
This change makes a waiting check report the real underlying problem when a connection fails, instead of showing a generic cancellation message. It helps teams understand what went wrong faster and reduces confusion when a run stops unexpectedly.
Original PR description
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because…
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because it's a blocking wait on a request it yield a confusing result as the run fails with `CancelledError` and the actual cause (the WS was closed) is lost. One option would be to `set_exception` on the waiting responses, but I feel like this could create other confusing knock-on effects e.g. more evented waits which currently get ignored might start raising exceptions (although that seems unlikely as callbacks apparently do get called on cancel), and since issues with cancelling only seem to appear in `_wait_ready` that seems like overkill. Instead have `_wait_ready` handle cancellation by first checking if the result is in error, and using that to raise the underlying error, otherwise retry (and ultimately timeout, probably). And while at it, before signaling a timeout check if the run is in failure and raise that immediately, just in case. https://runbot.odoo.com/odoo/error/233738 Forward-Port-Of: odoo/odoo#260324
Resolved issues and error corrections
Fixed an issue on invoices where choosing today’s date for a currency rate did nothing. Users can now select today and have the correct rate applied, making currency conversion selection behave as expected.
Original PR description
On an invoice, using the date picker to choose the currency rate did not allow picking today's date. Steps to reproduce: - Activate a currency - Add currency rate for today, yesterday and tomorrow - Create a new invoice - Select the newly activated currency - Pick yesterday's date - Pick today's date Current behavior: picking today's date close the date picker without doing anything Expected behavior: picking today's date close the date picker and apply today's currency rate (or latest if today's doesn't exist) Cause: The date picker was opened with today's date selected, preventing selecting it again. Opening the date picker with the right date selected isn't possible as we don't save the currency rate date. It would require doing a reverse search among the currency rate date which might be wrong as the currency rate can be customized. opw-6046169 Forward-Port-Of: odoo/odoo#258368
The currency rate service now uses a configurable timeout when contacting mindicador.cl instead of a fixed 30-second limit. This helps avoid missed daily exchange rate updates when the external service is slow, reducing gaps in stored currency rates.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
This fix ensures that employee working schedule hours are recalculated when the day period is changed. It prevents errors in attendance views and keeps schedule data accurate after edits to lunch, morning, afternoon, or full-day periods.
Original PR description
Since #217895, `duration_hours` is now stored and needs to be recomputed when we change the attendance's `day_period` from lunch to morning/afternoon/full_day otherwise we will run into division by 0 in `_get_attendance_intervals_days_data`. ### Steps to reproduce 1. Change the day period of one of the working hours of a working schedule from Lunch to Morning. 2. Open the attendance overview including the attendances of an employee that has the working schedule from step 1. opw-6129881 Forward-Port-Of: odoo/odoo#259904
Approval request printouts now fall back to the request owner’s language when no contact is set, instead of losing translations. This ensures printed approvals appear in the expected language even when the contact field is optional.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
Mobile portal users can now upload files into shared document folders reliably. This fixes an issue where selecting a file did not complete the upload on phones because the upload menu closed too early.
Original PR description
Steps to reproduce: 1. Install `documents` 2. Create a portal user and share a document folder with edit access 3. Log in as the portal user on a mobile device 4. Try to upload a document inside the…
Steps to reproduce:
1. Install `documents`
2. Create a portal user and share a document folder with edit access
3. Log in as the portal user on a mobile device
4. Try to upload a document inside the shared folder
Issue:
- After selecting a file from the file picker, the document is not uploaded.
Cause:
- On mobile in the portal flow, Upload is triggered from a nested dropdown (inside New) inside the adaptive control-panel dropdown (bottom sheet). By default, DropdownItem uses closingMode="all", so tapping Upload closes parent dropdowns immediately. That unmounts the hidden <input type="file"> before the OS file picker returns. When the user comes back, the input no longer exists, so change never fires and upload does not start.
- Admin/internal users do not hit the same nested adaptive-dropdown path in this view
Solution:
- Set closingMode="'none'" on the Upload DropdownItem so the menu stays mounted while the native picker is open. After a file is selected and onFileInputChange starts upload, close the bottom sheet programmatically with: `window.dispatchEvent(new Event("popstate"))`
opw-5937105
Forward-Port-Of: odoo/enterprise#108486This fix prevents an error when exporting the General Ledger for a Peruvian company that includes draft invoice entries. Users can now complete the export normally, even when some accounting entries are not yet finalized.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
This change prevents access errors that could appear when users set or update suppliers in replenishment for products shared across multiple companies. It ensures only the appropriate company’s suppliers are used, so users can work without unexpected interruptions.
Original PR description
Issue before this commit: ------------------------------------------ In replenishment (multi-company setup), a 'read' access error occurs while setting the supplier, changing the replenishment unit,…
Issue before this commit: ------------------------------------------ In replenishment (multi-company setup), a 'read' access error occurs while setting the supplier, changing the replenishment unit, or changing the min/max when there are suppliers across multiple companies. Steps to reproduce: ------------------------------------------ 1. Install purchase_stock. 2. Create a storable product. 3. Add one vendor for company A and one vendor for company B. 4. Make sure that only company A is active. 5. Create an orderpoint for company A (min/max = 0) and set the route to 'Buy'. 6. Try to set the vendor. Notice that an access error occurs. Cause of the issue: ------------------------------------------ This issue occurs because the `seller_ids` cache gets polluted with suppliers from multiple companies. As a result, when `self.seller_ids` is accessed [1], it returns vendors from both active and non-active companies, ignoring the current company context. [1] https://github.com/odoo/odoo/blob/47deb9f13627a26d6a3179399bd965f639fde436/addons/product/models/product_product.py#L1016 Since users are not allowed to read records from non-active companies, this leads to a read access error when those supplier records are accessed. * Cause of the cache pollution: The cache gets polluted with records from another company because `product.seller_ids` [2] is accessed in a `sudo()` environment. This happens due to the `qty_to_order_computed` field, which is stored and computed. By default, stored computed fields use `compute_sudo=True`, causing the computation to run in a `sudo()` environment and cache cross-company sellers. [2] https://github.com/odoo/odoo/blob/d11b56f9272be39169d382007d19d63739617a8a/addons/purchase_stock/models/stock_rule.py#L169 Solution: ------------------------------------------ Filter the sellers in sudo mode as well, since the `seller_ids` cache will otherwise always be polluted due to the sudo environment. opw-6034990 Forward-Port-Of: odoo/odoo#259403
This update fixes an issue that could stop users from creating accrual entries after changing the review date. The system now handles the date consistently, preventing a type mismatch error and allowing the process to complete normally.
Original PR description
**Steps to reproduce:** - Install the `accountant` and `purchase` modules. - Create and confirm a Purchase Order (with 1 quantity). - Create a vendor bill using `auto-complete` from the PO, set the…
**Steps to reproduce:** - Install the `accountant` and `purchase` modules. - Create and confirm a Purchase Order (with 1 quantity). - Create a vendor bill using `auto-complete` from the PO, set the quantity to 1, and `confirm` it. - Navigate to Accounting > Review > `Billed Not Received`. - Change the `date` from the top left. - Select a record and click `Create Accrual Entries`. **Error:** `TypeError: '<=' not supported between instances of 'datetime.date' and 'str'` **Root cause:** At [1], the `accrual_entry_date` is set in the context as a `string`. Later, at [2], this value is retrieved from the context and used directly in a comparison with `ivl.date`, which is a `datetime.date`. **Fix:** This commit converts `accrual_entry_date` to a `datetime.date` object at [2], allowing users to create accrual entries without errors. [1]: https://github.com/odoo/enterprise/blob/3ab460a935c6caf013202ec6be1c3708178c8d7d/account_reports/static/src/views/accrual_list_controller.js#L61-L76 [2]: https://github.com/odoo/odoo/blob/7e17c788babc2715e85456467db9172bb0b8e42d/addons/account/wizard/accrued_orders.py#L166-L188 opw-6110907 Forward-Port-Of: odoo/odoo#260415 Forward-Port-Of: odoo/odoo#259047
When a vendor bill is created using Auto-complete from a previous bill, the Intrastat transaction information is now preserved on the new bill lines. This prevents missing reporting data and helps ensure EU trade declarations remain accurate without manual re-entry.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#114520 Forward-Port-Of: odoo/enterprise#112857
This fix ensures return names show the correct calendar year when a return spans the start of a year. As a result, users will no longer see labels like "Jan 2022 - Apr 2023" for periods that actually start in January 2023.
Original PR description
Steps to reproduce: - Create a return from Jan 2023 to April 2023 -> the dates displayed in the name will be Jan 2022 - Apr 2023 The display is incorrect because we used the wrong date format, and therefore switch from using YYYY to yyyy as the first one is the ISO standard year and the second the calendar year. They might differ on the result here because 01 Jan 2023 falls on a Sunday, but ISO week starts on Monday, so it took the previous year (2022) Forward-Port-Of: odoo/enterprise#114428
This fix prevents the IoT box from overwriting a printer’s manually chosen subtype when devices are sent again after a restart. As a result, user settings stay intact and the printer keeps the correct configuration instead of reverting unexpectedly.
Original PR description
Steps to reproduce: 1. Connect a printer to the IoT box and pair with a DB 2. Manually change the subtype of the printer in the DB 3. Restart the IoT box so it resends its devices. **Expected behaviour**: Subtype remains as the user-set value. **Actual behaviour**: Subtype is reset to the original value. To fix this issue, we simply remove any check for subtype in the device updating condition. Now, a device will only reset if its type changes. Forward-Port-Of: odoo/enterprise#114416
Generating a W-2 CSV now works even when the End Date is left blank. If no end date is provided, the system automatically uses the current year for the file name instead of failing, which avoids a blocking error for users.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#114363
Forward-Port-Of: odoo/enterprise#113408This update removes a duplicate credit note selection in the Colombian e-invoicing setup. It prevents an error that could stop the invoice form from opening correctly when creating a credit note.
Original PR description
The `l10n_co_edi_operation_type` field on `account.move` had two entries with the same selection value `'23'`:
('23', 'Nota Crédito para facturación electrónica V1 (Decreto 2242)'), ('23', 'Inactivo: Nota Crédito para facturación electrónica V1 (Decreto 2242)'),
This caused an OWL crash when opening the invoice form:
"Got duplicate key in t-foreach: 23"
__Steps to reproduce:__
1- Install the l10n_co_edi module
2- switch to colombian company
3- Activate the developer mode
4- Go to Credit Note > Create
__NOTE__: The javascript error is only visible on version 18.4 but the duplicate selection is present since 17.0.
opw-5969595
Forward-Port-Of: odoo/enterprise#112841This update adjusts the width and layout of grid columns in monthly timesheet views. It prevents icons and overtime values from overlapping or wrapping awkwardly, making the display clearer and easier to read.
Original PR description
# [FIX] web_grid: column width with new time widget in month This commit increases the default width of the grid columns. Prior to this, the magnifying glass in Timesheets overlapped with the times in month scale, because the columns were too small. # [FIX] timesheet_grid: column overtime layout Without this commit, the overtimes were spanning two lines because the columns were too small. This commit changes the layout so that it spans one line to be consistent with the grid values. task-6121017
This change updates the packaging setup so Windows builds include the optional dependencies they need. It helps prevent installation or runtime issues for users deploying Odoo on Windows.
Original PR description
Forward-Port-Of: odoo/odoo#258320 Forward-Port-Of: odoo/odoo#258128
Self-billed invoices are now matched to the correct company when multiple companies are registered on Peppol. This prevents invoices from being assigned to the wrong business entity and helps keep accounting records accurate.
Original PR description
Currently, if a database has multiple companies registered on Peppol, receiving a self-billed invoice may assign it to the wrong company. The system was searching the journal using a domain that included all companies (in self), instead of filtering by the correct current company. Steps to reproduce: - Create a database with 2 companies, both on Peppol - Receive a self-billed invoice from a random other company on Peppol - The received invoice will potentially be assigned to the wrong company This is only a test forward-port of #257380 opw-6045669 Forward-Port-Of: odoo/odoo#259524 Forward-Port-Of: odoo/odoo#259072
Images added to the company document layout now print correctly even when their width is set as a percentage. This prevents logos or other inserted images from disappearing in PDF output, improving the reliability of printed documents.
Original PR description
Problem: When adding an image in the `company_details` field via **Settings > Configure your document layout** and resizing it to a percentage width (e.g. 50%), the image is not visible when printed. Cause: Since fa55c2d1, `wkhtmltopdf` fails to correctly calculate percentage-based image widths because none of the ancestor elements have an explicit width defined. Solution: Force the wrapping table to `width: 100%`, giving `wkhtmltopdf` a concrete width to resolve percentage values against. Steps to reproduce: - Go to **Settings > Configure your document layout** - In the address field, add an image via `/media` - Resize the image to 50% - Print the document - Image is missing in the PDF output opw-6102568 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259077
This update fixes the exemption code and exemption reason used for the Belgian 0% S tax. It helps ensure invoices and tax reporting use the correct legal classification, reducing the risk of incorrect records or submissions.
Original PR description
The tax 0% S had a wrong tax exemption code and tax exemption reason. This commit corrects it. Task-6127195 Forward-Port-Of: odoo/odoo#259639
20 changes
Enhancements to existing features
This change improves how the system reports failures when a connection drops during a wait. Instead of showing a confusing cancellation message, it now surfaces the real underlying problem so support teams can identify the cause more quickly.
Original PR description
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because…
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because it's a blocking wait on a request it yield a confusing result as the run fails with `CancelledError` and the actual cause (the WS was closed) is lost. One option would be to `set_exception` on the waiting responses, but I feel like this could create other confusing knock-on effects e.g. more evented waits which currently get ignored might start raising exceptions (although that seems unlikely as callbacks apparently do get called on cancel), and since issues with cancelling only seem to appear in `_wait_ready` that seems like overkill. Instead have `_wait_ready` handle cancellation by first checking if the result is in error, and using that to raise the underlying error, otherwise retry (and ultimately timeout, probably). And while at it, before signaling a timeout check if the run is in failure and raise that immediately, just in case. https://runbot.odoo.com/odoo/error/233738 Forward-Port-Of: odoo/odoo#260324
The website’s video snippet preview now uses a lightweight SVG image instead of an embedded video. This reduces ongoing maintenance and makes the preview more reliable over time.
Original PR description
Prior to this PR, the `s_video` inner snippet was using a video as placeholder, which implied maintenance to ensure the video is always available. To avoid maintenance and ensuring long term effectiveness, we replace this video with a `SVG` placeholder, similarly to what has been done for the `s_image`. task-5441285 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#260042
Resolved issues and error corrections
When users create a vendor bill by auto-completing from a previous bill, the Intrastat transaction information is now kept on the copied lines. This avoids missing reporting data and helps ensure bills are prepared correctly for EU-related transactions.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#114520 Forward-Port-Of: odoo/enterprise#112857
This fix prevents an error when exporting the General Ledger in Peruvian companies if draft invoice entries are included. Users can now complete the export successfully without the report failing on unfinished documents.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
The invoice currency rate date picker now lets users select today’s date correctly. This fixes a frustrating issue where choosing today did nothing, so the system now applies today’s exchange rate, or the latest available rate if today’s is missing.
Original PR description
On an invoice, using the date picker to choose the currency rate did not allow picking today's date. Steps to reproduce: - Activate a currency - Add currency rate for today, yesterday and tomorrow - Create a new invoice - Select the newly activated currency - Pick yesterday's date - Pick today's date Current behavior: picking today's date close the date picker without doing anything Expected behavior: picking today's date close the date picker and apply today's currency rate (or latest if today's doesn't exist) Cause: The date picker was opened with today's date selected, preventing selecting it again. Opening the date picker with the right date selected isn't possible as we don't save the currency rate date. It would require doing a reverse search among the currency rate date which might be wrong as the currency rate can be customized. opw-6046169 Forward-Port-Of: odoo/odoo#258368
This fix ensures approval request printouts are translated even when no contact is linked to the request. If a contact language is unavailable, the system now falls back to the request owner's language, or to the default language when needed.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
This change makes the timeout for the Mindicador currency rate service configurable instead of fixed. It helps avoid missed daily exchange-rate updates when the external service is slow, reducing gaps in stored rates and keeping currency data more reliable.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
This update prevents an access error that could appear when choosing a vendor or adjusting replenishment settings in a multi-company setup. It makes supplier selection behave correctly even when products have vendors linked to more than one company, so users can work without unexpected interruptions.
Original PR description
Issue before this commit: ------------------------------------------ In replenishment (multi-company setup), a 'read' access error occurs while setting the supplier, changing the replenishment unit,…
Issue before this commit: ------------------------------------------ In replenishment (multi-company setup), a 'read' access error occurs while setting the supplier, changing the replenishment unit, or changing the min/max when there are suppliers across multiple companies. Steps to reproduce: ------------------------------------------ 1. Install purchase_stock. 2. Create a storable product. 3. Add one vendor for company A and one vendor for company B. 4. Make sure that only company A is active. 5. Create an orderpoint for company A (min/max = 0) and set the route to 'Buy'. 6. Try to set the vendor. Notice that an access error occurs. Cause of the issue: ------------------------------------------ This issue occurs because the `seller_ids` cache gets polluted with suppliers from multiple companies. As a result, when `self.seller_ids` is accessed [1], it returns vendors from both active and non-active companies, ignoring the current company context. [1] https://github.com/odoo/odoo/blob/47deb9f13627a26d6a3179399bd965f639fde436/addons/product/models/product_product.py#L1016 Since users are not allowed to read records from non-active companies, this leads to a read access error when those supplier records are accessed. * Cause of the cache pollution: The cache gets polluted with records from another company because `product.seller_ids` [2] is accessed in a `sudo()` environment. This happens due to the `qty_to_order_computed` field, which is stored and computed. By default, stored computed fields use `compute_sudo=True`, causing the computation to run in a `sudo()` environment and cache cross-company sellers. [2] https://github.com/odoo/odoo/blob/d11b56f9272be39169d382007d19d63739617a8a/addons/purchase_stock/models/stock_rule.py#L169 Solution: ------------------------------------------ Filter the sellers in sudo mode as well, since the `seller_ids` cache will otherwise always be polluted due to the sudo environment. opw-6034990 Forward-Port-Of: odoo/odoo#259403
Fixed an issue that prevented portal users on mobile devices from uploading files into shared document folders. The upload action now stays active long enough for the phone’s file picker to complete, so selected files are uploaded correctly.
Original PR description
Steps to reproduce: 1. Install `documents` 2. Create a portal user and share a document folder with edit access 3. Log in as the portal user on a mobile device 4. Try to upload a document inside the…
Steps to reproduce:
1. Install `documents`
2. Create a portal user and share a document folder with edit access
3. Log in as the portal user on a mobile device
4. Try to upload a document inside the shared folder
Issue:
- After selecting a file from the file picker, the document is not uploaded.
Cause:
- On mobile in the portal flow, Upload is triggered from a nested dropdown (inside New) inside the adaptive control-panel dropdown (bottom sheet). By default, DropdownItem uses closingMode="all", so tapping Upload closes parent dropdowns immediately. That unmounts the hidden <input type="file"> before the OS file picker returns. When the user comes back, the input no longer exists, so change never fires and upload does not start.
- Admin/internal users do not hit the same nested adaptive-dropdown path in this view
Solution:
- Set closingMode="'none'" on the Upload DropdownItem so the menu stays mounted while the native picker is open. After a file is selected and onFileInputChange starts upload, close the bottom sheet programmatically with: `window.dispatchEvent(new Event("popstate"))`
opw-5937105
Forward-Port-Of: odoo/enterprise#108486This fixes the displayed name of return periods so the starting year now matches the actual calendar year. Previously, some dates could be shown as the prior year because the system used the wrong year format, which could confuse users reviewing reports.
Original PR description
Steps to reproduce: - Create a return from Jan 2023 to April 2023 -> the dates displayed in the name will be Jan 2022 - Apr 2023 The display is incorrect because we used the wrong date format, and therefore switch from using YYYY to yyyy as the first one is the ISO standard year and the second the calendar year. They might differ on the result here because 01 Jan 2023 falls on a Sunday, but ISO week starts on Monday, so it took the previous year (2022) Forward-Port-Of: odoo/enterprise#114428
The W-2 report can now generate a CSV file even when the End Date is left blank. If no end date is provided, the system uses the current year for the file name instead of failing with an error.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#114363
Forward-Port-Of: odoo/enterprise#113408This fix makes sure that when a work schedule’s time period is changed, the related duration is recalculated automatically. It prevents errors in attendance views and keeps employee schedules displaying correctly.
Original PR description
Since #217895, `duration_hours` is now stored and needs to be recomputed when we change the attendance's `day_period` from lunch to morning/afternoon/full_day otherwise we will run into division by 0 in `_get_attendance_intervals_days_data`. ### Steps to reproduce 1. Change the day period of one of the working hours of a working schedule from Lunch to Morning. 2. Open the attendance overview including the attendances of an employee that has the working schedule from step 1. opw-6129881 Forward-Port-Of: odoo/odoo#259904
This change updates the Windows packaging setup so it includes optional dependencies required for a smoother installation and runtime experience. It helps avoid missing-component issues for Windows users and makes the packaged product more reliable.
Original PR description
Forward-Port-Of: odoo/odoo#258320 Forward-Port-Of: odoo/odoo#258128
The Belgian 0% S tax setup has been updated with the correct exemption code and exemption reason. This helps ensure invoices and tax reports use the proper official classification, reducing the risk of reporting errors.
Original PR description
The tax 0% S had a wrong tax exemption code and tax exemption reason. This commit corrects it. Task-6127195 Forward-Port-Of: odoo/odoo#259639
This update ensures product costs are calculated correctly when some stock is owned by a supplier or other external party. It prevents company-owned inventory from being undervalued in stock views and valuation screens, helping finance and operations see accurate stock values.
Original PR description
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco…
edit : the issue was fixed by https://github.com/odoo/odoo/pull/257103 So this commit only contains these use cases tests **Steps to reproduce:** - enable consignement setting - create a tracked avco product with a cost of 10 - click on the quantities smart button and then "update quantity" to open the quants view - create one line with a quantity of 1 and no owner - create one line with a quantity of 1 and an owner outside the company **Current behavior:** problem A: open the 'stock' view and look for your product, the unit cost is 5 problem B: navigate back to the quants view of the product, unhide the value column, the value is 5 for the non consigned quant **Expected behavior:** problem A: the unit cost should be 10 (because consigned product shouldn't be taken into account when computing the unit cost) problem B: the non consigned quant value should be 10 for the same reason **Cause of the issue:** problem A: Inside _compute_value(), to compute total_value_by_company_id, we use _with_valuation_context() https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L196-L203 which excludes consigned products https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L362-L364 So when we iterate through 'products' and fetch qty_available for our product the value is going to be 1. But when computing avg_cost at the end of the method, we iterate through 'self', so we don't have this context anymore and the value of qty_available is 2. https://github.com/odoo/odoo/blob/6c107cd70e2228d3428e53cf8095aba17f678d8a/addons/stock_account/models/product.py#L271-L273 That's because qty_available is computed with _compute_quantities() which depends on context (including owner_id) https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock/models/product.py#L148-L152 problem B: when computing the value of the quant, there is no context specifying that the consigned quantities should be excluded https://github.com/odoo/odoo/blob/53f7d1dd2f972921ba91f6083a49f50749a3f503/addons/stock_account/models/stock_quant.py#L61-L62 opw-6049413 Forward-Port-Of: odoo/odoo#257013
Updating an attendance record will no longer reset overtime entries that were already approved in the same week. This keeps manager approvals intact unless the overtime calculation itself changes, reducing repeated review work and confusion.
Original PR description
Creating or updating an attendance record resets previously approved overtime entries in the same week back to the 'to_approve' status. ### **Steps to reproduce:** 1) Install Attendance with demo…
Creating or updating an attendance record resets previously approved overtime entries in the same week back to the 'to_approve' status. ### **Steps to reproduce:** 1) Install Attendance with demo data. 2) Set 'Extra Hours Validation' to 'Approved by Manager' in settings. 3) Ensure an overtime rule is set for the Admin user. 4) Create an attendance for Admin with some overtime. 5) Navigate to management and approve overtime. 6) Create another attendance with overtime for Admin in the same week. 7) Navigate back to management. ### **Observed Behavior:** Previously approved overtime reappears in the list, requiring approval again. ### **Expected Behavior:** Previous overtime should remain in the 'approved' status, provided its calculated duration has not changed. ### **Root Cause:** When an attendance is added or modified, the [_get_overtimes_to_update_domain](https://github.com/odoo/odoo/blob/3891dd471d64629634644c0b022a171bbaa65b49/addons/hr_attendance/models/hr_attendance.py#L268-L286) method evaluates the entire week regardless of the ruleset. This means any daily attendance update wipes and recreates the entire week. ### **Fix:** Check the ruleset of the employee. If no rule has `quantity_period` set to **'week'**, restrict the domain to the specific days of the attendances being modified, rather than the entire week. **opw-6054497** Forward-Port-Of: odoo/odoo#256281
This change corrects how self-billed invoices are matched when more than one company is registered on Peppol. It ensures each incoming invoice is assigned to the right company, preventing accounting entries from being created under the wrong legal entity.
Original PR description
Currently, if a database has multiple companies registered on Peppol, receiving a self-billed invoice may assign it to the wrong company. The system was searching the journal using a domain that included all companies (in self), instead of filtering by the correct current company. Steps to reproduce: - Create a database with 2 companies, both on Peppol - Receive a self-billed invoice from a random other company on Peppol - The received invoice will potentially be assigned to the wrong company This is only a test forward-port of #257380 opw-6045669 Forward-Port-Of: odoo/odoo#259524 Forward-Port-Of: odoo/odoo#259072
When someone types an email address in the editor, it is now automatically turned into a clickable email link as soon as they press space. This makes it easier to create email links correctly and improves the editing experience.
Original PR description
Before this commit: when typing an email address, it's not converted to a mailto link after spacing. After this commit: the mailto link is created after spacing. task- 6053993 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#258736 Forward-Port-Of: odoo/odoo#257497
Users without stock permissions can now copy Helpdesk tickets that include product information without triggering an access error. This avoids a blocking issue and makes ticket handling smoother for support teams with limited access rights.
Original PR description
Steps to reproduce: - Install helpdesk_sale_timesheet. - Create a Helpdesk Ticket and set its sale_line_id. - Log in as a user without stock.group_stock_user access. - Try to duplicate the ticket. Issue: Duplicating a ticket raises an AccessError because the user lacks stock rights required when copying the product_id. Fix: Set `product_id` to False during duplication for non-stock users. Reference: https://github.com/odoo/enterprise/pull/9100 task-5356318 Forward-Port-Of: odoo/enterprise#114266 Forward-Port-Of: odoo/enterprise#101338
This change fixes an unstable automated test in the HTML editor so it no longer fails randomly on slower systems. It does not change customer-facing behavior, but it makes the test suite more dependable and reduces false alarms during validation.
Original PR description
Waiting for a full animation frame is too dangerous. In the general case, an animation frame happens every 16ms, in which case the power buttons haven't been updated yet since they have a debouncing timeout of 30ms. However, when the runbot is slow, more than 30ms may very well have elapsed between two animation frames. When that is the case, the power buttons are displayed and the test fails. This commit changes the forced awaiting of an animation frame to a waiting pased on the time passed. In the general case, an animation frame will have happened in 20ms, so the test will still catch a regression. When the runbot is slow however, more time might have passed, but not necessarily an animation frame, so the power buttons should still be invisible, making this test more reliable. runbot-242466 Forward-Port-Of: odoo/odoo#259854 Forward-Port-Of: odoo/odoo#259654
3 changes
Resolved issues and error corrections
This update fixes an error that could stop the General Ledger report from exporting when draft invoices or other draft entries were included. Users in Peruvian companies can now generate the report normally, improving reliability for accounting teams.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
When an approval request does not have a contact linked, the printed report now falls back to the request owner’s language instead of stopping translation. This ensures the document is shown in the expected language even when the contact field is optional.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
The system now lets administrators adjust the timeout used when fetching exchange rates from mindicador.cl. This helps prevent daily currency rate updates from being skipped when the external service is slow, avoiding gaps in stored exchange rates.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
4 changes
Enhancements to existing features
This update makes test waits report the real underlying problem when a connection is lost, instead of showing a generic cancellation message. It also checks for an existing failure before timing out, which helps surface the true cause faster and makes debugging easier.
Original PR description
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because…
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because it's a blocking wait on a request it yield a confusing result as the run fails with `CancelledError` and the actual cause (the WS was closed) is lost. One option would be to `set_exception` on the waiting responses, but I feel like this could create other confusing knock-on effects e.g. more evented waits which currently get ignored might start raising exceptions (although that seems unlikely as callbacks apparently do get called on cancel), and since issues with cancelling only seem to appear in `_wait_ready` that seems like overkill. Instead have `_wait_ready` handle cancellation by first checking if the result is in error, and using that to raise the underlying error, otherwise retry (and ultimately timeout, probably). And while at it, before signaling a timeout check if the run is in failure and raise that immediately, just in case. https://runbot.odoo.com/odoo/error/233738 Forward-Port-Of: odoo/odoo#260324
Resolved issues and error corrections
This change makes the waiting time for the Mindicador exchange-rate service configurable instead of fixed. It helps prevent daily currency rate updates from being skipped when the external service is slow, reducing gaps in exchange rate records.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
When printing an approval request, the document now falls back to the request owner’s language if no contact is set. This prevents reports from appearing in the wrong language or without translations in cases where the contact field is optional.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
Miscellaneous changes
Forward-Port-Of: odoo/enterprise#114395 Forward-Port-Of: odoo/enterprise#114366
Original PR description
Forward-Port-Of: odoo/enterprise#114395 Forward-Port-Of: odoo/enterprise#114366
7 changes
Enhancements to existing features
This update speeds up the validation of large stock transfers by grouping line deletions and creations into fewer operations. It reduces repeated database work, which helps prevent timeouts and makes big pickings complete much faster.
Original PR description
Before this PR, `button_validate` was using a `write()` call per matched stock move. On every `write()` there is a Command.create and Command.delete which is resulting in N database round-trips for…
Before this PR, `button_validate` was using a `write()` call per matched stock move. On every `write()` there is a Command.create and Command.delete which is resulting in N database round-trips for the unlinks and N for the creates, followed by N separate `_apply_putaway_strategy()` calls. This is problematic for pickings with many move_ids. This PR attempts to accumulates all move lines to delete and to create. Then performs a single `unlink()` and `create()`, followed by a single `_apply_putaway_strategy()` for all pickings. Unlink is done using `.sudo()` to preserve the superuser context that was previously inherited implicitly through the `purchase_order.sudo().search` that produced the recordset used to obtain the `receipt_move`(s). Benchmarks: | No. move lines in delivery | Before | After | | -------------------------- | ------- | ----- | | 7579 | Timeout | < 200 s | opw-5826905 Forward-Port-Of: odoo/enterprise#110587 Forward-Port-Of: odoo/enterprise#110153
Resolved issues and error corrections
This fix prevents an error when exporting the General Ledger for Peruvian companies that includes draft invoices or other draft entries. Users can now complete the export normally without the process stopping due to missing entry names.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
Printed approval requests now fall back to the requester’s language when no contact is linked, instead of missing translations. This ensures approval documents are readable in the expected language even when the contact field is optional.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
This update corrects an automated test for Mexican electronic invoicing after a related rounding change was reverted to its expected behavior. It helps ensure the invoice rounding logic stays reliable and prevents false test failures during development and delivery.
Original PR description
https://github.com/odoo/odoo/pull/255574 change the rounding mode back to mixed. This break the test modified in this PR. opw-5963855 Forward-Port-Of: odoo/enterprise#114081
The currency rate update process now uses a configurable timeout when calling the mindicador.cl service. This reduces the risk of missed daily exchange rates when the provider is slow, helping avoid gaps in currency rate records.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
When creating a vendor bill by auto-completing from a previous bill, the Intrastat information will now be kept on the copied lines. This prevents missing trade declaration data and helps ensure reports stay complete and accurate.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
This update adds an identifier so Sendcloud can recognize requests coming from Odoo and continue using the current API flow for these users. It helps avoid connection issues during Sendcloud’s API transition and ensures a smoother experience for customers using shipping integration.
Original PR description
Sendcloud pass their api v2 to maintenance and only provide new api V3 key to the new customers. In order to make a smooth transition for the user we add the partner key, so they know that the customer are coming from odoo and they use the v2 api. Future work will be done to upgrade our module and support the v3. API key. Forward-Port-Of: odoo/enterprise#114441
32 changes
Security fixes and vulnerability patches
The AI website builder now sanitizes generated HTML and CSS before use. This reduces the risk of unsafe or unwanted content appearing on websites, helping businesses rely on AI-generated pages with greater confidence.
Enhancements to existing features
The timesheet kanban views have been redesigned to show more useful information at a glance, with the personal timesheet view now feeling more like a calendar. This should make it easier for users and managers to review time entries, billable work, and overall timesheet status without opening individual records.
Original PR description
Redesign the timesheet kanban views to display more relevant information and make the *My Timesheet* view feel more calendar‑like. ## Additional - To ensure `is_billable` behaves correctly with the kanban progress bar, a non-stored `is_billable_select` field was added to `analytic.account.line`. This field can be queried through its `sql_search` method, allowing efficient access without introducing redundant stored fields in the database. Using a selection field is required for proper progress bar functionality. task-[5180328](https://www.odoo.com/odoo/project/4105/tasks/5180328) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users now see a warning as soon as they assign someone and choose planned dates that overlap with that person's existing tasks. This helps teams spot conflicts earlier and adjust schedules before saving, reducing planning mistakes.
Original PR description
When a user plans a task, they are not aware if the assigned user already has other tasks at the same time. Currently, the overlapping warning is only triggered when the task is saved. This commit ensures that the warning appears as soon as the user selects the assigned user and planned dates, allowing the user to reschedule the task before saving. task-4300405
Helpdesk teams can now see the coupon email and its attachment directly in the related ticket chatter. This makes it easier to track what was sent to customers and keeps the ticket history complete for follow-up and audits.
Original PR description
Log the coupon email and the attachment in the helpdesk chatter --- Task-5075162
Belgian payroll now applies caps to Premium Pay calculations, helping ensure employee payslips follow the required limits. This reduces payroll errors and improves compliance for companies using Belgian payroll rules.
Original PR description
add premium pay caps Task: 6119891
The French reporting export screen now allows longer text lines to wrap instead of being cut off. This makes export information easier to read and reduces confusion for users reviewing async export details.
Original PR description
Improves the UI by allowing the text lines to wrap and fully be visible. No task ID
The accounting reports setup screen no longer shows an informational warning about reports using custom handlers. This reduces clutter for users who customize reports and removes a message that is no longer considered useful.
Original PR description
Before this commit: - We had one info banner with the message indicating that the report is using a custom handler, so a change in the parameters used for computation could lead to errors. After this commit: - Now, we are removing this info banner from the report form view, because there is no need for this banner anymore, as if the user wants to customize the reports, they'll do it anyway. Task-6037421
This update changes how VoIP-related records are stored internally to better handle frequent creation and deletion of calls, messages, and related items. Users should not see workflow changes, but the app may feel smoother and more responsive during busy usage.
Original PR description
`Store.MyModel.records` is an object whose key is record local id and value is the record. While format of object is nice, this object has its shape changing quite often as this is based on creation and deletion of records. Objects in javascript are expected to have their shape changed rarely, which is not the case of `records`. In theory, creation of JS models can lead to noticeable stuttering from major and minor GC. This commit changes the shape of `records` to become a Map instead, which doesn't have these problems. As this becomes a Map, and quite some business code was using `Object.values()` around records, this commit also add a new feature on Model object: `.all()`, which returns list of all records of the given model: ```js // previously Object.values(store.MyModel.records); // now store.MyModel.all(); ``` Task-5437248
The Documents app now keeps page navigation visible in Kanban and List views, even when the details panel is open. This makes it easier for users to move through document pages without changing panel visibility, and the details panel now updates to show the current folder when pages are opened or changed.
Original PR description
Before this commit, the pager would only be displayed if the right panel is invisible. This commit allows to be always displayed in `Kanban` and `List` views regardless of the state of the right panel. task-6070904
The Belgian payroll module now includes the 2026 salary scale values for Joint Committee 302, covering both regular and flexi jobs. This helps ensure payroll calculations stay aligned with the latest sector requirements and that related checks continue to validate the updated amounts.
Original PR description
. Add JC302 salary scale 2026 effective values for normal & flexi jobs . Update the corresponding tests task-6127071
The settings text for the Invoicing Switch Threshold now explains that all entries created by Invoicing before the threshold date are ignored, not just invoices. This helps users better understand what data is excluded and reduces confusion during accounting setup.
Original PR description
The previous "Invoicing Switch Threshold" explanation was misleading as it said only invoices prior to the threshold date is not taken into account. The explanation is updated to state that all entries created by Invoicing before the threshold date will be ignored. task-5940144 Forward-Port-Of: odoo/enterprise#113635
Resolved issues and error corrections
Approval request reports now still translate correctly when no contact is selected. If the contact language is unavailable, the report uses the request owner’s language or the system default, ensuring users receive printed approvals in the expected language.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
The UAE financial audit report test data was updated to match the latest account codes from the new chart of accounts. This keeps automated checks aligned with the current accounting setup and helps avoid false test failures.
Original PR description
in the odoo PR we changed a lot of the account codes. in this pr we are just fixing a test where the csv was still comparing old account codes in the CSV task-5455978
The Chilean currency rate provider can now wait longer when the source service is slow, instead of failing after a fixed 30 seconds. This helps avoid missed daily exchange rates and reduces manual corrections caused by temporary delays from mindicador.cl.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
Companies that are not based in Belgium but use Belgian taxes can now see and manage Intervat settings. This lets users change or disable the automatic Intervat redirection when Belgian accounting is enabled through a Belgian fiscal position.
Original PR description
### Issue: When demo data is disabled, creating a Belgian fiscal position installs the Belgian taxes and enables BE accounting Starting from 19.0, Intervat redirection is enabled automatically, but the Intervat settings are not available because the company itself is not Belgian As a result, the Intervat configuration cannot be changed or disabled ### Cause: The Intervat settings were only shown when the company country was Belgium However, companies using Belgian taxes through `account_enabled_tax_country_ids` must also be considered ### Steps to reproduce: - Disable demo data and install `accountant` - Create a Fiscal Position "Belgium" (Country: Belgium, Foreign Tax ID: BE010203040) - Click the alert to install the Belgian taxes - Open Settings Before the fix: The Intervat settings are not available opw-6068480 Forward-Port-Of: odoo/enterprise#112609
This fix makes French fiscal declaration exports more complete and reliable before they are sent to the ASPone platform. It adds missing report information, improves company data checks before export, and corrects small errors that could affect tax filing submissions.
Original PR description
This commit aims to make the xml that we send to aspone for the liasse fiscale is the more complete as possible and to correct some small bugs. - Add missing fields in the reports - Add missing tags in the xml - Add a data validation on company data before exporting the reports - Correct errors in the reports - Add country fields in the reports as many2one task-6128878
This fixes an issue where adding a configurable employee benefit could cause an error if no salary summary existed for the same contract structure. Benefits are now shown consistently, preventing interruptions during salary package configuration.
Original PR description
Cause: After this task https://www.odoo.com/odoo/project/1251/tasks/5419466, the showing of benefits was restricted by mistake to only when there was a salary summary for the same structure type. This meant that adding a configurable benefit would result in a traceback, since the template was then used to get more info later on. Fix: Always show configurable benefits, even if there is no salary summary for the same structure type. task-6126621
This fix makes an age-related Belgian payroll test use a fixed date so results no longer change as time passes. It prevents intermittent nightly build failures and improves confidence in payroll validation checks without changing customer-facing payroll behavior.
Original PR description
The test was failing intermittently in nightly builds that run at a date in the next year (e.g.: 2027-04-20). The issue was that the student's age is calculated at runtime using : - When the student is age 19 (2026): min wage = 2057.87 < 2100 → PASS - When the student is age 20 (2027): min wage = 2136.84 > 2100 → FAIL task-6144986 Runbot error: https://runbot.odoo.com/odoo/runbot.build.error/242589
Opening an AI agent chat from the systray or command palette now brings the conversation to the front in full-screen Discuss. This prevents users from thinking the action failed and makes access to AI assistance more reliable.
Original PR description
Prior to this commit, when opening the chat with an agent from the systray button, the chat window was opened in the background. This commit fixes the issue by adding a call to `channel.open` which opens the chat when in full-screen mode. This commit also fixes an issue where the chat window wasn't properly opened when done from the command palette. task-5172978
The accounting reports return name now shows the correct calendar year for date ranges that start near the beginning of January. This prevents confusing labels such as showing January 2022 for a return that actually starts in January 2023.
Original PR description
Steps to reproduce: - Create a return from Jan 2023 to April 2023 -> the dates displayed in the name will be Jan 2022 - Apr 2023 The display is incorrect because we used the wrong date format, and therefore switch from using YYYY to yyyy as the first one is the ISO standard year and the second the calendar year. They might differ on the result here because 01 Jan 2023 falls on a Sunday, but ISO week starts on Monday, so it took the previous year (2022) Forward-Port-Of: odoo/enterprise#114428
The deduplication screen now correctly hides the discard button when users are viewing records that have already been discarded. This avoids confusion and prevents users from trying to discard records again, including when only some records in a duplicate group are discarded.
Original PR description
Ensure the discard button is hidden in the deduplication view when displaying discarded records, including cases where only part of a duplicate group is discarded and shown through the archive/discarded filter. task-6124494
Signed files added from a project or task now automatically select the project's configured Documents folder instead of defaulting to My Drive. This keeps signed project paperwork organized in the same place as other project attachments and reduces manual filing.
Original PR description
Steps to Reproduce --- - Request a signature from a project task or project and complete the signing process. - In the chatter, click "Add to Documents" on the signed attachment. Issue --- Signed documents attached to projects or tasks default to "My Drive" when added to Documents, instead of using the project's configured Documents folder. Current Behaviour --- - Regular task/project attachments correctly preselect the project Documents folder. - Signed attachments fall back to "My Drive". Expected Behaviour --- Signed documents linked to projects or tasks should preselect the project's Documents folder, consistent with regular attachments. Fix --- Extend get_documents_operation_add_destination to handle sign.request attachments linked to project.task or project.project, resolving to the corresponding project Documents folder. task - 5226770 Forward-Port-Of: odoo/enterprise#105600
Restarting an IoT box no longer resets a printer subtype that a user manually selected. This prevents unwanted configuration changes and keeps device settings aligned with business preferences.
Original PR description
Steps to reproduce: 1. Connect a printer to the IoT box and pair with a DB 2. Manually change the subtype of the printer in the DB 3. Restart the IoT box so it resends its devices. **Expected behaviour**: Subtype remains as the user-set value. **Actual behaviour**: Subtype is reset to the original value. To fix this issue, we simply remove any check for subtype in the device updating condition. Now, a device will only reset if its type changes. Forward-Port-Of: odoo/enterprise#114416
Vendor bills created with auto-complete now keep the correct Intrastat transaction details from the original bill. This helps EU companies avoid missing trade reporting information and reduces manual corrections.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#114520 Forward-Port-Of: odoo/enterprise#112857
The W-2 report CSV export no longer fails when the End Date field is left blank. In that case, the file name now uses the current year, allowing payroll users to generate the report successfully.
Original PR description
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined. Steps to replicate: - Install `l10n_us_hr_payroll`. - Open Payroll > Reporting > W2 Report. - Click…
Currently, an error occurs when user tries to create a csv for w2 form with no end date defined.
Steps to replicate:
- Install `l10n_us_hr_payroll`.
- Open Payroll > Reporting > W2 Report.
- Click `New` > Remove value from `End Date` and click Generate.
Error:
```
File '/home/odoo/odoo19/enterprise/l10n_us_hr_payroll/models/l10n_us_w2.py', line 249, in action_generate_csv
self.csv_filename = f'form_w2_{self.date_end.year or date.today().year}.csv'
^^^^^^^^^^^^^^^^^^
AttributeError: 'bool' object has no attribute 'year'
```
Cause:
- As the user did not give any value for `End Date`, False was passed and when the execution flow reached [here] `self.end_date` is False and attempting to access `self.end_date.year` results in this error.
Solution:
- If we do not receive the `self.end_date` while generating the CSV, we will use the current year to generate the CSV file name.
[here]: https://github.com/odoo/enterprise/blob/01be8d6e9384bcb340559847d529b4887e073519/l10n_us_hr_payroll/models/l10n_us_w2.py#L248
No ID
Forward-Port-Of: odoo/enterprise#114363
Forward-Port-Of: odoo/enterprise#113408Rental planning now correctly applies calendar leave entries that are not tied to a specific resource to all resources. This helps prevent availability and scheduling errors when company-wide unavailable periods are configured.
Original PR description
Before this commit, any `Resource Calendar Leave` created with no `Resource` related to it was ignored, while it should have been applied to all `Resources`. This commit makes sure that any `Resource Calendar Leave` with no related `Resource` is applied to all `Resources` as intended. task-5798796 Forward-Port-Of: odoo/enterprise#114274 Forward-Port-Of: odoo/enterprise#112575
Self-ordering now loads only the point-of-sale configuration and session information it actually needs. This reduces unnecessary data handling, helping the self-ordering experience run more efficiently without changing how users interact with it.
Original PR description
This commit optimizes pos_config and pos_session data loading by only loading the fields required for self-ordering. X-original-commit: ce78609b368e541a70c17141ee5b51543c73c1d0 Forward-Port-Of: odoo/enterprise#113801 Forward-Port-Of: odoo/enterprise#113661
The employee form in Swiss payroll now shows the contract template button with styling that matches the surrounding interface. This removes visual inconsistency and makes the form look more polished for users.
Original PR description
Fix contract template button styling: remove incorrect classes and align font-size and border with the surrounding UI task-6068488 Forward-Port-Of: odoo/enterprise#112113
Users without inventory access can now duplicate Helpdesk tickets without encountering an access error. The fix avoids copying restricted product information for those users and also prevents a related refund access issue, keeping helpdesk workflows moving for non-stock staff.
Original PR description
Steps to reproduce: - Install helpdesk_sale_timesheet. - Create a Helpdesk Ticket and set its sale_line_id. - Log in as a user without stock.group_stock_user access. - Try to duplicate the ticket. Issue: Duplicating a ticket raises an AccessError because the user lacks stock rights required when copying the product_id. Fix: Set `product_id` to False during duplication for non-stock users. Reference: https://github.com/odoo/enterprise/pull/9100 task-5356318 Forward-Port-Of: odoo/enterprise#114266 Forward-Port-Of: odoo/enterprise#101338
The ecommerce product page now shows rental availability based on the customer’s selected rental period, even when “continue selling” is enabled. This prevents shoppers from seeing misleading stock numbers and helps businesses communicate accurate rental availability before checkout.
Original PR description
**Issue**: The displayed available quantity on the ecommerce product page is incorrect for rental products when "continue selling" is enabled. **Steps to reproduce**: - Create a rental product…
**Issue**: The displayed available quantity on the ecommerce product page is incorrect for rental products when "continue selling" is enabled. **Steps to reproduce**: - Create a rental product tracked in stock with a quantity of 5 - Enable "continue selling" and "show available quantity below 10" - Go to the ecommerce page of this product - Rent 3 units for a given period, confirm and pay - Return to the ecommerce product page -> Whatever the selected renting period, the displayed quantity is always 2 **Cause**: The website displays `free_qty`: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/static/src/xml/website_sale_stock_renting_product_availability.xml#L15 `free_qty` is computed in: https://github.com/odoo-dev/odoo/blob/0935829ddaecd7b2b6eec9157f8f790b546d06ff/addons/website_sale_stock/models/product_template.py#L36 which leads to: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/models/website.py#L10 and ultimately relies on: https://github.com/odoo/odoo/blob/37bf1703c7478a3010b71cd60bbb43b3295a605b/addons/stock/models/product.py#L213 This computation does not take the selected renting period into account. There is a period-aware computation here: https://github.com/odoo/enterprise/blob/41c729e22c5fd1abb690f8335e933f793be0b319/website_sale_stock_renting/models/website.py#L15C17-L21C1 but it is only triggered when `product.allow_out_of_stock_order` is False (i.e. when "continue selling" is disabled). opw-[5354163](https://www.odoo.com/web#id=5354163&view_type=form&model=project.task) Forward-Port-Of: odoo/enterprise#108493 Forward-Port-Of: odoo/enterprise#103333
When users select all documents across multiple pages, the Share panel now includes every selected file instead of only the files visible on the current page. This ensures permission changes are applied consistently to the full selection, preventing missed documents in large batches.
Original PR description
**Steps to reproduce:** - Install Documents app - Upload more than 80+ files (max page size is 80) - Use the checkbox to select all files on the page - Click the 'Select All' button in the control panel to select allfiles - Use Share action button - Pop-up only takes the current page into account - Rights modifications will not be applied on remaining records **Issue:** `onShare()` only takes current records into account even if the full selection was applied. **Fix:** Fetch all document ids (if needed) before opening the dialog. opw-5957777 Forward-Port-Of: odoo/enterprise#110299
The Peruvian reporting export no longer fails when draft invoices are included in the General Ledger. This helps users generate Inventory and Balance reports reliably without needing to post every invoice first.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#114550 Forward-Port-Of: odoo/enterprise#113405
4 changes
Resolved issues and error corrections
When creating a vendor bill from a previous bill using Auto-complete, the Intrastat transaction details are now preserved on the new bill lines. This prevents missing trade reporting information and helps ensure compliance and accurate reporting.
Original PR description
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to…
Currently, Intrastat transaction values are not set when creating a vendor bill using the `Auto-complete` feature based on a previously created vendor bill for an `EU customer`. **Steps to reproduce:** - Install `account_intrastat` and `l10n_de` modules and switch to a `DE company`. - Create a vendor bill for an `EU partner`, add a product, and set an `Intrastat` (enable from the optional column if needed). - `Confirm` the bill and note its number. - Create a new vendor bill for the `same partner`. - Use the `Auto-complete` feature by selecting the previous bill. - Check the invoice lines. **Observation:** The `Intrastat` is missing from the generated invoice lines. **Root Cause:** - On using `Auto-Complete`, `_onchange_invoice_vendor_bill` at [1] copies invoice lines using `copy_data()`. - However, in `account_intrastat`, `copy_data()` at [2] removes `intrastat_transaction_id`. **Fix:** This commit ensures that `Intrastat` is properly set when creating a vendor bill using the auto-complete feature based on a previously created vendor bill for an EU customer. [1]: https://github.com/odoo/odoo/blob/07b72963c665f2fe5b741b8815f2351129a2271c/addons/account/models/account_move.py#L1808-L1820 [2]: https://github.com/odoo/enterprise/blob/4da85b58a28837379e4839327ea914bd6aa70bf9/account_intrastat/models/account_move.py#L77-L83 opw-5936869 Forward-Port-Of: odoo/enterprise#112857
This change prevents the general ledger export from failing when draft entries are included. It allows users in the Peru localization to generate the report successfully even if some accounting items do not yet have a final document number.
Original PR description
**Steps to reproduce:** - Install the `l10n_pe_reports_lib` module and switch to a `PE company`. - Create a draft invoice. - Navigate to Reporting > General Ledger. - Click the gear icon and select `Inventory and Balance`. **Error:** AttributeError: 'NoneType' object has no attribute 'replace' **Root Cause:** For draft entries, `move_name` is `None`, and calling `.replace()` on it causes an error at [1]. **Fix:** This commit prevents errors and ensures users can export the general ledger even when draft entries are included. [1]: https://github.com/odoo/enterprise/blob/5babcb5cb951e0e7beebdbef0781a20a7a19c319/l10n_pe_reports_lib/models/account_general_ledger.py#L168 opw-6104117 Forward-Port-Of: odoo/enterprise#113405
The daily currency rate update process now uses a configurable wait time when connecting to the Mindicador service instead of a fixed 30-second limit. This helps avoid missed rate updates when the service is slow, reducing gaps in stored exchange rates.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
Printing an approval request now falls back to the request owner’s language when no contact is set. This ensures the report is translated correctly instead of appearing in the default language when the contact field is empty.
Original PR description
Steps to reproduce: ------------------ 1. Install Approvals. 2. Select an approval type from Approvals > Configuration and ensure the 'Contact' field is not required. 3. Install a second language (e.g., Arabic) and switch the user's language. 4. Create a new approval request with this approval type and set user as the request owner. 5. Try to print the approval request. Current behavior: ----------------- The report is only translated when partner is present because it translates using `partner_id.lang`. Since the partner is not required in all cases, `lang` can evaluate to False when it is missing, causing the report to bypass translations. Expected behavior: ------------------ The report should fall back to the request owner's language or the system's default language if the partner is not available. opw-6010222 Forward-Port-Of: odoo/enterprise#112476
7 changes
Enhancements to existing features
This update makes failed background readiness checks report the real underlying problem instead of a generic cancellation message. It helps users and support teams understand when a connection has failed and avoids confusing timeout-style errors.
Original PR description
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because…
This case induces confusion in the ranks: when the WS connection fails, the result of the run is set to failure then every outstanding response is cancelled. For `_wait_ready` specifically, because it's a blocking wait on a request it yield a confusing result as the run fails with `CancelledError` and the actual cause (the WS was closed) is lost. One option would be to `set_exception` on the waiting responses, but I feel like this could create other confusing knock-on effects e.g. more evented waits which currently get ignored might start raising exceptions (although that seems unlikely as callbacks apparently do get called on cancel), and since issues with cancelling only seem to appear in `_wait_ready` that seems like overkill. Instead have `_wait_ready` handle cancellation by first checking if the result is in error, and using that to raise the underlying error, otherwise retry (and ultimately timeout, probably). And while at it, before signaling a timeout check if the run is in failure and raise that immediately, just in case. https://runbot.odoo.com/odoo/error/233738 Forward-Port-Of: odoo/odoo#260324
Resolved issues and error corrections
The currency rate update for mindicador.cl now uses a configurable timeout instead of a fixed 30-second limit. This helps avoid missed daily rate updates when the external service is slow, reducing gaps in currency rate records.
Original PR description
The mindicador.cl provider had a hardcoded 30s timeout on its HTTP requests. The mindicador.cl service is sometimes slow around rate publication time, causing read timeouts that make the cron silently skip currency rate creation for the day due to HTTP Timeouts, leaving permanent gaps in res.currency.rate. Make the timeout configurable through the `mindicador_api_timeout` system parameter (defaults to the previous 30s). opw-6126027 Forward-Port-Of: odoo/enterprise#114153
When converting a lead into a new contact, CRM was incorrectly copying the contact’s email, phone, and mobile number to the parent company as well. This fix keeps the company record separate, so customer details stay accurate and do not overwrite each other.
Original PR description
Steps to reproduce: 1. Install `CRM` 2. Activate leads from the settings 3. Create a lead with `Contact Name`, `Company Name` and `Email` 4. Convert this lead to an opportunity with `action` and customer set to `convert to opportunity` and `Create a new contact` 5. Now look into contact and contacts's parent company Issue: - Both created contact partner and company partner have the same email Solution: - Remove `email` from the data based on `company name` availability while creating a customer opw-5421940
This fix ensures that when users cancel a confirmation prompt in the spreadsheet app, the expected cancel action is actually triggered. It improves reliability of user interactions and prevents workflows from continuing as if the dialog had been accepted.
Original PR description
The `cancel` callback of the `env.askConfirmation` method was not called when the user clicked on the cancel button. task-6074948 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 fix ensures that when users cancel a confirmation dialog in Documents Spreadsheet, the cancel action is properly executed. It improves reliability by making sure the application responds as expected when a user chooses not to proceed.
Original PR description
The `cancel` callback of the `env.askConfirmation` method was not called when the user clicked on the cancel button. task-6074948 Forward-Port-Of: odoo/enterprise#112304
This change fixes an issue where invoicing timesheet-based work could show the wrong quantity when timesheets were entered using days instead of hours. It ensures the system uses the correct base unit for conversion, so invoices reflect the actual work logged.
Original PR description
**Steps to reproduce:** 1. Install sale_timesheet. 2. Set timesheet encoding UoM to "Days". 3. Create a quotation with a timesheet-based product: - Set quantity = 1 - Set UoM to "Days" (ensure both…
**Steps to reproduce:** 1. Install sale_timesheet. 2. Set timesheet encoding UoM to "Days". 3. Create a quotation with a timesheet-based product: - Set quantity = 1 - Set UoM to "Days" (ensure both SOL and timesheet UoM are in the same category) 4. Confirm the quotation and open the "Recorded" smart button. 5. Log 1 day of timesheet. 6. Create an invoice using a timesheet period (starting from SO date). 7. Check the invoice quantity. **Issue:** The invoice quantity is incorrectly set to 8 days instead of 1. **Cause:** https://github.com/odoo/odoo/blob/426dc7d7164a95020c1435625801e291990c865c/addons/sale_timesheet/models/sale_order_line.py#L182 Since commit a1517de, the logic utilizes the **timesheet encoding UoM** as the reference unit for conversions. When the Sales Order Line (SOL) UoM and the timesheet UoM share the same category, the system calls `_compute_quantity` under the assumption that `unit_amount` is expressed in the timesheet UoM. However, `unit_amount` actually stored time in hours regardless of the encoding UoM. When the timesheet UoM is set to "Days," the system treats the raw hour value (e.g., 8.0) as if it were already in days during the conversion process, bypassing the necessary hour-to-day conversion and resulting in inflated invoice quantities. https://github.com/odoo/odoo/blob/426dc7d7164a95020c1435625801e291990c865c/addons/uom/models/uom_uom.py#L231-L232 **Solution:** Use hours as the reference unit instead of the timesheet UoM when calling `_compute_quantity`, ensuring the source unit matches the actual unit of `unit_amount`. opw-6077311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Bills imported from Poland’s KSeF service now correctly handle both net and gross unit prices. This prevents imported vendor bills from being created with zero prices and ensures the invoice matches what the supplier reported.
Original PR description
**PROBLEM** When receiving bills from KSeF, we don't handle gross unit price and default to a price_unit of 0.0. Leading to an incorrect invoice. When generating the bill, the vendor can choose to report the net unit price (P_9A) or gross unit price (P_9B). We need to handle both cases. opw-6066027
2 changes
Resolved issues and error corrections
This fix corrects when the “Update Payment” button is shown on Mexican electronic invoices. In batch payment cases, the system now evaluates the payment information properly so the button disappears when it should, avoiding confusion for users.
Original PR description
backport of f41900a4353ea867b08f71ed64f8702a13411bac - Create one invoice with the PUE payment policy. - Create another invoice with the PDD payment policy. - Send both invoices to the CFDI. - Create a batch payment for both and reconcile. - Click on Update Payment on one of the invoices. The Update Payment button does not disappear. In the method _l10n_mx_edi_cfdi_invoice_get_payments_diff, we compare the current UUIDs and the previous UUIDs to determine if the button should be shown. However, when there is a batch payment, the current UUID list includes the UUIDs of all invoices in the batch, including the PUE payment (which should normally be filtered out by the continue). The previous UUID list includes only the UUID of the PDD payment. opw-6055781
When an employee is archived while they are still checked in, the system now ensures their attendance is properly closed. This prevents mismatches where an employee looks inactive but still has an open attendance record, which could cause reporting and process issues for HR.
Original PR description
- Step to reproduce: with attendance installed and an employee checked in, archive that employee by HR user. If missing attendance rights, the employee will be archived but not checked out from its ongoing attendance. - Cause: if no role set for Attendance (default), no permission to update the employee attendance while archiving. - Solution: using sudo method so that any user with sufficient rights to archive an employee, can trigger check out of the corresponding attendance. Inheriting from employee departure wizard and adding a warning if ongoing attendance so the hr user can choose to checkout or delete the attendance. Task: 6131692