Daily updates from Odoo
Friday, July 31, 2026
52 changes · saas-19.1
Resolved issues and error corrections
The Timesheets overtime display now keeps the selected unit, such as days, even when users switch to another language. This prevents confusing differences where the same remaining time could appear as hours instead of days for translated users.
Original PR description
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet…
Steps to reproduce: ------------------- 1. Install Timesheets. 2. Create a new employee with a fully fixed working schedule (40h/week). 3. Open Timesheets > All Timesheets and create a new timesheet in the past week for this employee (e.g. 8 hours). 4. Observe the overtime indicator for the employee (it shows 32 hrs) (Click the left arrow to display it). 5. Change the timesheet encoding unit to "Days / Half-Days". 6. Return to Timesheets and observe the overtime indicator (it now correctly shows 4 days). 7. Install a language other than English (e.g. French). 8. Return to Timesheets and observe the overtime indicator again. Issue: -------- The remaining time value changes unexpectedly and displays 32 hours instead of 4 days. Cause: --------- In `get_timesheet_and_working_hours_for_employees`, the code determines whether the timesheet UoM is expressed in days by comparing the UoM name with the string `"days"`. Since UoM names are translatable, this comparison becomes invalid when the user language changes (e.g. `"jours"` in French), causing the logic to skip the day conversion and return values in hours instead. https://github.com/odoo/enterprise/blob/c48290e90fdeadf4f9ca8c44b035e601e7ed380a/timesheet_grid/models/hr_employee.py#L165-L169 Solution: ----------- Compare the timesheet UoM record with the day UoM record directly instead of relying on translated string values. see commit: https://github.com/odoo/enterprise/commit/5fbf194c5056566453a124812fd2614edfe19a82 opw-6279133 Forward-Port-Of: odoo/enterprise#126114 Forward-Port-Of: odoo/enterprise#120595
Polish JPK tax exports now use the vendor bill reference in the purchase document field when one is provided. This helps exported tax files match supplier documentation and supports compliance with Polish reporting expectations.
Original PR description
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting >…
**Steps to reproduce:** - Install the `l10n_pl_reports` module and switch to a `PL Company`. - Create and confirm a vendor bill with a `Bill Reference` and `Taxes`. - Navigate to Accounting > Reporting > Tax Report and select `This Month`. - From the dropdown, click `JPK` > `Export XML`. - Open the generated XML file and observe the `DowodZakupu` field. **Observation:** `DowodZakupu` contains the vendor `Bill Number` even when a `Bill Reference` is set. **Root Cause:** At [1], `DowodZakupu` is populated only with the vendor `Bill number`(`move_name`) instead of using the `Bill reference`(`ref`) when available. **Fix:** This commit ensures `DowodZakupu` contains the `Bill Reference` when it is available in JPK exports. **Reference:** https://www.podatki.gov.pl/media/eqrn3dey/broszura-jpk_vat-z-deklaracj%C4%85-od-1-lutego-2026-r-en.pdf (page 41) [1]: https://github.com/odoo/enterprise/blob/4b0404058b280136f6865090562f95e18d4d7e0b/l10n_pl_reports/data/jpk_export_templates.xml#L208 opw-6299827 Forward-Port-Of: odoo/enterprise#126113 Forward-Port-Of: odoo/enterprise#121117
This fix prevents cancellation attempts in German point-of-sale certification from being rejected when an active transaction lacks receipt details. It adds a safe default cancellation receipt only when needed, helping stores avoid failed cleanup of active transactions while preserving existing transaction data.
Original PR description
When cancelling active transactions, the schema was forwarded as-is from the listed transaction. ACTIVE transactions can have an empty schema, and Fiskaly rejects the cancellation PUT with:
{
"code": "E_TX_NO_TYPE_DEFINED",
"message": "`schema.raw.process_type` must be defined for
updating or finishing a transaction",
"status_code": 409,
"error": "Conflict"
}
Fall back to a minimal CANCELLATION receipt schema when the transaction has no schema, while preserving any schema that is already present.
opw-6345005
Forward-Port-Of: odoo/enterprise#122130This fix prevents the Journal Report from crashing when an invoice contains a tax that was originally a group of taxes but was later changed to a percentage tax. Accounting users can now open the audit report reliably even after tax configuration changes.
Original PR description
**Steps to reproduce:** - Install account_reports - Create a tax * Tax Computation: Group of Taxes * Definition: [Add a tax] - Create an invoice with that tax - Confirm the invoice - Edit the tax by changing "Tax Computation" to "Percentage" - Go to "Accounting / Reporting / Audit Reports / Journal Report" **Issue:** A KeyError is raised. **Cause:** While generating the data, a group of taxes is found in the journal items. When trying to retrieve its info from the dict listing the groups of taxes, its ID is not found but the system assumes that it's present. opw-6377465 Forward-Port-Of: odoo/enterprise#125291
Employees lists could fail when showing document counts across multiple companies. The update calculates counts separately for each relevant employee group, so HR users can open the full employee list without errors in multi-company setups.
Original PR description
Steps to reproduce: ------------------- 1. Install `documents_hr` and `web_studio` with demo data. 2. Add `document_count` to the Employees list view via Studio. 3. Create a second company with an…
Steps to reproduce:
-------------------
1. Install `documents_hr` and `web_studio` with demo data.
2. Add `document_count` to the Employees list view via Studio.
3. Create a second company with an employee, enable multi-company.
4. Open Employees list, click **All** in the search panel.
Issues:
------
Issue 1:
```python
File "/home/odoo/odoo/enterprise/documents_hr/models/hr_employee.py", line 25, in _compute_document_count
if not self.company_id.documents_hr_settings:
File "/home/odoo/odoo/community/odoo/orm/fields.py", line 1429, in __get__
record.ensure_one()
File "/home/odoo/odoo/community/odoo/orm/models.py", line 5640, in ensure_one
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: res.company(1, 2)
```
Issue 2:
```python
File "/home/odoo/odoo/enterprise/documents_hr/models/hr_employee.py", line 31, in _compute_document_count
('partner_id', '=', self.work_contact_id.id)
File "/home/odoo/odoo/community/odoo/orm/fields_misc.py", line 117, in __get__
raise ValueError("Expected singleton: %s" % record)
ValueError: Expected singleton: res.partner(9, 8, 7)
```
Cause:
---------
https://github.com/odoo/enterprise/blob/38674448e387159d28f98c1678856fcaf5f7f52e/documents_hr/models/hr_employee.py#L23-L48
1. The document count computation assumes all employees belong to the same company by directly accessing `self.company_id.documents_hr_settings`. In a multi-company environment, `self` may contain employees from different companies, making self.company_id a multi-recordset and triggering a singleton error.
2. Similarly, when `documents_hr_settings` is disabled, the fallback computation accesses `self.work_contact_id` on a multi-recordset, causing another singleton error.
Solution:
-----------
Split the employees based on whether `documents_hr_settings` is enabled and compute each group separately.
Additionally, use the current employee's `work_contact_id` in the fallback computation to avoid singleton error.
**NOTE:**
This has been resolved from saas-19.4 onward with this improvement [commit](https://github.com/odoo/enterprise/commit/d018d8205300b434728129e199ae048cefbaa296).
opw-6351141
Forward-Port-Of: odoo/enterprise#126099
Forward-Port-Of: odoo/enterprise#124826This change removes an incorrect update that was carried forward from an older version where it was no longer needed. It prevents an error in the bank reconciliation quick create flow, helping accountants continue their work without interruption.
Original PR description
This commit https://github.com/odoo/enterprise/commit/e559d9f5acbd176792db0dedc4e1f0cad7271457 fixed a problem only happening in 19.0. The commit shouldn't have been forward ported. no task id
Payroll decimal precision settings will no longer be reset to default values when the payroll module is upgraded. This protects company-specific payroll configuration and avoids unexpected changes after maintenance updates.
Original PR description
decimal.precision records are user-configurable settings that may be adjusted per company needs. With noupdate="0", every module upgrade resets the 'Payroll' and 'Payroll Rate' precision values back to their defaults, silently discarding any customization made by the user. This is inconsistent with the standard pattern used across Odoo modules. For example, the 'quality' module correctly loads its decimal.precision records with noupdate="1". The same convention is followed in core addons such as 'product' and 'account'. The forcecreate="True" attribute already ensures the records are created on fresh installations, so noupdate="1" only prevents overwriting existing values on upgrade — which is the expected behavior for configuration data. Forward-Port-Of: odoo/enterprise#120509
This fix ensures the Swedish point-of-sale test consistently completes order creation before finishing. It reduces random test failures, helping maintain confidence in the Swedish POS localization without changing business workflows.
Original PR description
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing:…
## Issue The tour `test_l10n_se_pos_01` does not consistently create its `pos_order`. This leads to the following assert failing: https://github.com/odoo/enterprise/blob/0f6f6fac892bc8cec477160a790d52fbf053be99/l10n_se_pos/tests/test_se_pos.py#L40-L42 ## Steps to reproduce 1. Install `l10n_se_pos` 2. Run the test `test_l10n_se_pos_01` 3. **The test fails non-deterministically** ## Fix We use `clickNextOrder()` at the end of the tour to ensure the creation of the order, like other tests already do (e.g., [FinishResidualOrder](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L676-L677), [test_name_preset_skip_screen](https://github.com/odoo/odoo/blob/7fc645e5a3fad9255432e7cc68d47bd0971d3d77/addons/pos_restaurant/static/tests/tours/pos_restaurant_tour.js#L1333-L1334), [PosOrderCreationTourPdis](https://github.com/odoo/enterprise/blob/08d5172a8c3310af0c51e18a281c544f83f5aed7/pos_enterprise/static/tests/tours/point_of_sale/pos_tour.js#L141-L142), ...). runbot-238568
The POS preparation display order-count badge now uses the same logic as the preparation screen. This keeps counts accurate for orders left open overnight and for orders removed by a reset, reducing confusion for staff monitoring kitchen or preparation queues.
Original PR description
Steps to reproduce: - Configure a preparation display on a POS config with a product category - Place an order and leave it in a non-final stage - Keep the session open past midnight Issue: The…
Steps to reproduce: - Configure a preparation display on a POS config with a product category - Place an order and leave it in a non-final stage - Keep the session open past midnight Issue: The kanban order-count badge drops the order once its create_date falls behind "today", while the preparation screen still lists it. The same divergence makes the badge keep counting an order that a "Reset" already removed from the screen. _compute_order_count() scoped its search on pos_config_id and create_date >= today, whereas the screen is built by get_preparation_display_order() from _get_open_orders_in_display() and _get_stageless_orders_in_display(), which have no date filter and instead bound the set by the order stage `done` flag and the session state. An order open across midnight is therefore in the screen set but not in the badge set. Conversely reset() marks the current stage done, which drops the order from the screen set, but the badge only skipped orders whose latest stage is the final stage, so an order reset while still in the first stage stayed counted. opw-6414302 Forward-Port-Of: odoo/enterprise#126139 Forward-Port-Of: odoo/enterprise#125984
Basic users can now open the spreadsheet creation window from Documents even when they cannot access spreadsheet templates. This removes an unnecessary blocker and lets them create blank spreadsheets consistently from the document view.
Original PR description
A basic user can access the document app and create all types of documents from the kanban view except for the spreadsheets because it requires an access to the templates. While the user cannot interact with the templates, they should have the possibility to create an empty spreadsheet. Note that it can already be done coming from the view of a spreadsheet! This revision ensures that the user can indeed access the spreadsheet creation modal even if they don't have access to the spreadsheet templates. Task-6364964 Forward-Port-Of: odoo/enterprise#126231 Forward-Port-Of: odoo/enterprise#123003
Rental orders using a custom Make-to-Order buying route now correctly create the expected return transfer when the order is confirmed. This prevents missing return logistics for rented products, helping teams track rentals reliably from delivery through return.
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes and rental transfers - Unarchive the MTO route - Create a rental product P with a buy route and a set vendor - Create a rental order for 1 x P and set the the MTO route on the sol - Confirm the order #### > The delivery as well as the purchase for 1 unit of P was generated but the return was not. ### Cause of the issue: The procurement generated to handle both the delivery and the return rental picking are handled by the `_create_procurements`: https://github.com/odoo/enterprise/blob/b0e48baaf99bdc4faefd2ffdd3bd5637fb548593/sale_stock_renting/models/sale_order_line.py#L353-L374 The `route_ids` set and used is the `mto_route` set on the sol: https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L415-L422 https://github.com/odoo/odoo/blob/0f061503e26ac8c441d62d91947419119e48c47a/addons/sale_stock/models/sale_order_line.py#L282-L297 However, in the present case, the mto route does not contain any rule with a relevant `location_src_id` in the rental location so that the return will not be generated. opw-6361322 Forward-Port-Of: odoo/enterprise#126078 Forward-Port-Of: odoo/enterprise#124097
Peruvian electronic invoices now use the current SUNAT-required address structure for UBL 2.1. This helps invoices validate correctly by formatting district and urban subdivision information according to the latest rules.
Original PR description
Update electronic invoicing address nodes to align with current SUNAT requirements. This transitions the geographic data formatting from the legacy UBL 2.0 schema to the standard UBL 2.1 specification, ensuring proper structural validation for districts and urban subdivisions. Documentation used: https://cpe.sunat.gob.pe/sites/default/files/inline-files/guia+xml+factura+version+2-1+1+0+(2)_0+(2).pdf opw-6282314 Forward-Port-Of: odoo/enterprise#121390
Fixes an Accounting Reports issue that could cause the Journal Audit report to fail after changing and removing the Generic Tax Report root report. This keeps accounting reporting accessible and avoids internal server errors for affected users.
Original PR description
Step To Reproduce: - Install the Accounting module. - Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report. - Set the Root Report to "Balance Sheet" and save. - Remove the…
Step To Reproduce:
- Install the Accounting module.
- Go to Accounting -> Configuration -> Accounting Reports -> Generic Tax Report.
- Set the Root Report to "Balance Sheet" and save.
- Remove the Root Report and save again.
- Open Accounting -> Reporting -> Journal Audit.
Issue:
Opening the Journal Audit report raises an Internal Server Error with: psycopg2.errors.UndefinedTable: missing FROM-clause entry for table "account_move_line__move_id"
Reason:
The code that recreates the missing "account.move" join was not updated consistently with the other "_join()" usages. Without calling "._sudo()", the ORM builds the join using a filtered subquery (for example, adding the company filter), which changes the generated join alias(https://github.com/odoo/odoo/blob/saas-19.1/odoo/orm/fields_relational.py#L559). The SQL query still references the regular alias (account_move_line__move_id), causing the query to fail.
Reference PR:- https://github.com/odoo/enterprise/pull/101230
Solution:
Use "query.table._sudo()._join()" when recreating the missing "account.move" join, matching the other "_join()" usages and ensuring the expected join alias is generated.
before fix:-
`'account_move_line__move_id__2': (SQL('JOIN'), SQL('(SELECT "account_move".* FROM "account_move" WHERE "account_move"."company_id" IN %s)', (1,)), SQL('"account_move_line"."move_id" = "account_move_line__move_id__2"."id"'))`
Query : `JOIN (
SELECT
account_move.*
FROM account_move
WHERE account_move.company_id IN (1)
) AS account_move_line__move_id__2
ON account_move_line.move_id = account_move_line__move_id__2.id`
after fix:-
`'account_move_line__move_id': (SQL('JOIN'), SQL('"account_move"'), SQL('"account_move_line"."move_id" = "account_move_line__move_id"."id"'))`
Query : `JOIN account_move AS account_move_line__move_id
ON account_move_line.move_id = account_move_line__move_id.id`
opw-6425842This fix ensures overtime calculations use the correct period setting, such as weeks instead of always treating rules as days. It prevents extra shifts from being incorrectly marked as overtime when public holidays fall within the affected period.
Original PR description
In the function '_get_expected_hours_from_contract', there is an improper super call where period is set to 'days' instead of passing in the value already passed into the original function. So when an overtime rule has a quantity_period not set to 'day', downstream calculations can go astray. In one example, when regenerating overtimes, weeks containing public holidays will have multiple shifts set as overtime shifts rather than just the shift on the holiday. Steps to recreate: 1. Create employee 2. Give them contract and flexible work schedule 3. On overtime ruleset, set overtime rule's quantity_period to Weeks (default is days) 4. Add a typical weeks worth of attendances 5. Create public holiday on one of the attendance days 6. Regenerate overtimes 7. See extra hours have been added to multiple shifts that week By fixing this super call, issues like these should be resolved going forward. opw-6373300 Forward-Port-Of: odoo/enterprise#126094
The German DATEV general ledger export now uses the correct foreign-to-base currency exchange rate and rounds it to six decimal places. This makes exported accounting files align with DATEV requirements and avoids overly long or incorrect rate values.
Original PR description
### Steps to Reproduce: 1. Activate l10n_de 2. Navigate to the General Ledger and export the "Datev DATA" 3. Column D, "Kurs," is incorrect ### Description of the issue/feature this PR addresses:…
### Steps to Reproduce: 1. Activate l10n_de 2. Navigate to the General Ledger and export the "Datev DATA" 3. Column D, "Kurs," is incorrect ### Description of the issue/feature this PR addresses: **Issue:** DATEV documentation states that the column for "Kurs" should be the ratio of WKZ-Umsatz : WKZ-Basisumsatz, which is Foreign : Base Currency. Additionally, all sample files show this column's values being rounded to 6 decimal places. Currently, when Odoo exports the general ledger as DATEV data, there is no rounding of decimal places and the formula does base / foreign amount, `line_amount / line_amount_currency`. **Solution:** In the `datev_export_csv.py` file, the relevant method is called `_l10n_de_datev_get_csv()`. In there, we can fix the line to round the value of `line_amount_currency / line_amount` to 6 decimal places. ### Current behavior before PR: Exporting the general ledger as DATEV data currently gives the reverse foreign currency rate and fails to round to 6 decimal places, which causes some values to be extremely long. ### Desired behavior after PR: The csv files should output the correct rate and be rounded appropriately. **Releted Documentation:** https://developer.datev.de/en/file-format/details/datev-format/format-description/booking-batch opw-6366276s Forward-Port-Of: odoo/enterprise#125097
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only
Original PR description
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's…
The AutoComplete component wraps a text input that already renders its own suggestion dropdown, so the browser's native suggestions must stay out of the way. In 12/2024 in this commit [1] the input's autocomplete was switched from `off` to `new-password` on the premise that `off` is not respected by browsers. In 02/2025, in this commit [2] then made it the component default so many2x pickers stay clean. Chrome runs two independent suggestion mechanisms, and each attribute silences only one of them: - `off` is ignored when the input has a name and Chrome holds autofill (address) data for it. - `new-password` is ignored when Chrome offers "frequently used values", i.e. the form-history dropdown. [3] So `new-password` does not always work. It only stays hidden while the field is ineligible for those suggestions. A field becomes eligible as soon as it gains an `id` and an associated `<label>`. On `saas-19.3` this is provable on commit [4] where adding a prefix icon gave the link popover URL input an `id` + `<label for>`, and the native dropdown resurfaced over the custom URL/page suggestions. This branch targets `saas-18.4`, where the regression is NOT reproducible because that URL input has no `id`/`label` yet. The fix is applied here anyway to avoid the gap that any later `label`/`id` addition re-exposes (as commit [4] proved), and the fix can be forward ported to `saas-19.3`. The website editor's URL field implements autocomplete without the `AutoComplete` component, so the default does not reach it. so `autocomplete="off"` is set directly on that input. [1]: https://github.com/odoo/odoo/commit/9c0f5612 [2]: https://github.com/odoo/odoo/commit/2980694b (opw-4551051) [3]: https://issues.chromium.org/issues/41163264#comment30 [4]: https://github.com/odoo/odoo/commit/2b4d04d1 (task-6034288) task-6370552 Forward-Port-Of: odoo/odoo#279203 Forward-Port-Of: odoo/odoo#277501
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387 Forward-Port-Of: odoo/odoo#279184 Forward-Port-Of: odoo/odoo#274398
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2
Original PR description
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through…
When a PoS runs in a currency other than the company currency, product prices are loaded already converted to the PoS currency (`list_price`, `lst_price`, `standard_price` all go through `_convert_pos_data_currency`). The prices carried by combos were not: `product.combo.base_price` is computed in the combo currency (the company currency) and `product.combo.item.extra_price` is stored in the product currency, but neither was converted when loaded in the PoS. As a result, a product priced at 2 USD (= 80 ZIG) was correctly shown as 80 ZIG on its own, yet appeared as 2 ZIG once it was part of a combo, since the raw amount was displayed as-is in the PoS currency. Convert `base_price` and `extra_price` from each record's own `currency_id` to the PoS currency at load time, mirroring what is already done for product prices. Steps to reproduce: - Set a product to 2 USD and a PoS to a ZIG pricelist (rate 40). - Open the PoS: the standalone product shows 80 ZIG. - Add the same product as a combo item: it shows 2 ZIG instead of 80 ZIG. opw-6410243 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278330
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating th
Original PR description
When a product with no attributes is sold, the description_picking field of the stock.move is empty. Steps to reproduce: ------------------- * Create a product with no attributes * Create a sale order with this product * Confirm the sale order > Observation: The description_picking field of the stock.move is empty The issue was originally reported because the e-Waybill in India had an empty description for the product. Why the fix: ------------ When trying to avoid duplicating the product name, we should first check that it would not result in an empty description picking. opw-6318785 Forward-Port-Of: odoo/odoo#275248
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used
Original PR description
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used while preserving the existing validation against empty or whitespace-only names. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279365 Forward-Port-Of: odoo/odoo#273593
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired Connection
Original PR description
Stripe recommends connecting to a reader returned by the most recent discovery call. However, the POS Stripe interface discovered readers as soon as the Stripe Terminal object was created, during POS loading. This means a POS reload performed long before the first payment could populate `pos.discoveredReaders` with stale reader objects. If the first Stripe Terminal payment happens much later, the SDK may try to connect using outdated reader/credential state and fail with an expired ConnectionToken. Move reader discovery to `connectReader()` so Odoo connects using fresh discovery results, and stop discovering readers eagerly when creating the Stripe Terminal instance. opw-6311626 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277765 Forward-Port-Of: odoo/odoo#276875
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Warehouses - Set your warehouse deliveries in two steps - Inventory > Operations > Tranfers > Internal > New - Set the operation type as Pick, set a partner and add Partner: Bob - In the sales & Purchase tab of the partner form set a customer location to be a child of the Customers location: Customers/Bob'Stock - Confirm and validate the Pick for 1 unit of a product
Original PR description
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Warehouses - Set your warehouse deliveries in two steps - Inventory >…
### Steps to reproduce: - In the settings enable: Multi-Steps Routes - Inventory > Configuration > Warehouse Management > Warehouses - Set your warehouse deliveries in two steps - Inventory > Operations > Tranfers > Internal > New - Set the operation type as Pick, set a partner and add Partner: Bob - In the sales & Purchase tab of the partner form set a customer location to be a child of the Customers location: Customers/Bob'Stock - Confirm and validate the Pick for 1 unit of a product P #### > A ship picking is created but the destination of the related move is still set to the default customer location. ### Note: If the flow is performed by a sale order, the `property_stock_customer` location will appropriately be used as `location_final_id`: https://github.com/odoo/odoo/blob/7609b5805c3704034b4d7813e2f356381ed18771/addons/sale_stock/models/sale_order_line.py#L297 https://github.com/odoo/odoo/blob/7609b5805c3704034b4d7813e2f356381ed18771/addons/sale_stock/models/sale_order_line.py#L306-L309 https://github.com/odoo/odoo/blob/720598d0315dbb91628441078febfd43ffefb431/addons/stock/models/stock_rule.py#L263-L264 So that the bug does not occur in that case. By contrast if the pick move is created manually, we do not set its `location_final_id` and hence do not propagate the info. Even though it looks expected to be set set as location_dest_id of the ship move sas suggested by the `stock.picking.location_dest_id` compute method : https://github.com/odoo/odoo/blob/fe3aea07a1964cd24f4c8ebf2bc93e483eca6b0b/addons/stock/models/stock_picking.py#L990-L1002 opw-6402483 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278838
Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#26751
Original PR description
Taxes with SAF-T code 21 and 22 are not correct and needed modification where they should be set to 0% because: - The foreign supplier invoices without Norwegian VAT, so the invoice total shouldn't increase - You must still self-assess 25% VAT and report it - The 25% is booked as both output and input VAT simultaneously → net cash effect = 0 - Only the basis amount is reported in the VAT return (import boxes) task-6254727 Forward-Port-Of: odoo/odoo#278896 Forward-Port-Of: odoo/odoo#267510
Once the cron is called to update current_version_id, the new employee calendar is applied to the previous version as well, due to the inverse on resource.resource def _inverse_calendar_id(self): for resource in self: if resource.calendar_id != resource.employee_id.resource_calendar_id: resource.employee_id.resource_calendar_id = resource.calendar_id All that because the introduced piece of code was called before super if 'current_versi
Original PR description
Once the cron is called to update current_version_id, the new employee calendar is applied to the previous version as well, due to the inverse on resource.resource
def _inverse_calendar_id(self):
for resource in self:
if resource.calendar_id != resource.employee_id.resource_calendar_id:
resource.employee_id.resource_calendar_id = resource.calendar_id
All that because the introduced piece of code was called before super
if 'current_version_id' in vals:
new_version = self.env['hr.version'].browse(vals.get('current_version_id'))
self.resource_id.calendar_id = new_version.resource_calendar_id
And this the inverse method was called on the previous version (not yet updated), not the new one.
Forward-Port-Of: odoo/odoo#279048Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#279171 Forward-Port-Of: odoo/odoo#271833
Original PR description
Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#279171 Forward-Port-Of: odoo/odoo#271833
Test `load dashboard that doesn't exist` sometimes fails because the test doesn't wait for the rpc to complete before checking the error message. This commit adds a wait for the next animation frame to ensure the rpc has completed before checking the error message. Runbot-940389 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/su
Original PR description
Test `load dashboard that doesn't exist` sometimes fails because the test doesn't wait for the rpc to complete before checking the error message. This commit adds a wait for the next animation frame to ensure the rpc has completed before checking the error message. Runbot-940389 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279418
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#271364
Original PR description
Allow to add the district node for the peruvian electronic invoicing. opw-6282314 Forward-Port-Of: odoo/odoo#271364
The navigator class, which adds event handlers, is instanciated on the setup of components using the useNavigation hook. However, before this commit, it was destroyed when the components were unmounted. It may happen that components are instanciated (setup is executed) but never mounted in the DOM, when the current rendering is cancelled. When this happened, the navigator cleanup wasn't executed, resulting in a small memory leak. This commit fixes the issue by using onWillDestroy instead.
Original PR description
The navigator class, which adds event handlers, is instanciated on the setup of components using the useNavigation hook. However, before this commit, it was destroyed when the components were unmounted. It may happen that components are instanciated (setup is executed) but never mounted in the DOM, when the current rendering is cancelled. When this happened, the navigator cleanup wasn't executed, resulting in a small memory leak. This commit fixes the issue by using onWillDestroy instead. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279322
to reproduce: ============= - Have a database with a large number of kit BoMs (e.g. ~160k phantom mrp.bom records). - Open Inventory Valuation. - The request never returns and hangs forever. problem: ======== Commit 11e9c1297439 started searching the valued products with `('qty_available', '!=', 0)`. On `product.product` this triggers the mrp override `_search_qty_available_new`, which loads every phantom BoM in the database and computes `qty_available` (via BoM explode) for each
Original PR description
to reproduce: ============= - Have a database with a large number of kit BoMs (e.g. ~160k phantom mrp.bom records). - Open Inventory Valuation. - The request never returns and hangs forever. problem:…
to reproduce:
=============
- Have a database with a large number of kit BoMs (e.g. ~160k phantom
mrp.bom records).
- Open Inventory Valuation.
- The request never returns and hangs forever.
problem:
========
Commit 11e9c1297439 started searching the valued products with
`('qty_available', '!=', 0)`. On `product.product` this triggers the mrp
override `_search_qty_available_new`, which loads every phantom BoM in the
database and computes `qty_available` (via BoM explode) for each kit. On top
of that, the override builds the kit products recordset with repeated
`kit_products |= ...` unions, which is O(n^2). With a large catalog of kits
the combination of O(n) heavy explodes and O(n^2) unions never returns.
On top of the performance issue, the new search dropped the kit exclusion
that `_get_accounts_by_product` previously applied through
`_get_valuation_product_domain` (`('is_kits', '=', False)` in mrp_account),
so phantom products - which are never valued on their own - were wrongly
pulled into the valuation.
solution:
=========
Restore the kit exclusion: search the valued products through
`_get_valuation_product_domain()` (which adds `('is_kits', '=', False)` in
mrp_account) instead of the ad-hoc `('is_storable', '=', True)` domain, so
phantom products are no longer valued.
Add a `skip_kit_qty_available` context key on `_search_qty_available_new` so
callers that intentionally exclude kits can skip the costly kit BoM expansion
and return the base (quant-based) result directly. The key is set in
mrp_account (via `_get_valuation_product_context`), alongside the domain that
already excludes kits, so the optimization and its precondition stay in the
same layer.
Also make the remaining kit path in `_search_qty_available_new` scale: build
the kit products recordset in a single pass instead of O(n^2) recordset
unions, and use a set for membership checks.
Benchmark:
==========
for `_get_report_data()` (averaged over 5 runs):
| # Input data (phantom kits) | Before PR | After PR |
| :---: | :---: | :---: |
| 1,000 | 2.558 s | 35.5 ms |
| 5,000 | 10.991 s | 41.6 ms |
| 10,000 | 20.869 s | 66.0 ms |
| 25,000 | 61.807 s | 80.7 ms |
| 50,000 | 195.382 s | 87.9 ms |
the improvement is **~99% faster**
opw-6312168
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#273982In the Italian localization, a bill should not be reset to draft once it has been sent to SDI. The exception is when the document was rejected or imported (0440cbab7a9cc183c7836fe58196799afdc00513). Steps to reproduce: - Create a vendor bill with l10n_it_edi enabled. - Send it to SDI. - The "Reset to Draft" button is still visible. opw-6350928 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273616
Original PR description
In the Italian localization, a bill should not be reset to draft once it has been sent to SDI. The exception is when the document was rejected or imported (0440cbab7a9cc183c7836fe58196799afdc00513). Steps to reproduce: - Create a vendor bill with l10n_it_edi enabled. - Send it to SDI. - The "Reset to Draft" button is still visible. opw-6350928 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273616
Issue: Hourly Time Off requests can keep the hours computed for the previous request date after the user changes the date when using custom working hours. Steps to reproduce: - Configure an employee schedule with Wednesday 07:30-16:15 and Thursday 07:30-16:30. - Create an hourly Time Off request on Wednesday (extra hours), Observe the hours are from 07:30-16:15. - Change the request date to Monday, Observe the hours will still be from 07:30-16:15 not 07:30-16:30. Cause: This was intro
Original PR description
Issue: Hourly Time Off requests can keep the hours computed for the previous request date after the user changes the date when using custom working hours. Steps to reproduce: - Configure an employee…
Issue: Hourly Time Off requests can keep the hours computed for the previous request date after the user changes the date when using custom working hours. Steps to reproduce: - Configure an employee schedule with Wednesday 07:30-16:15 and Thursday 07:30-16:30. - Create an hourly Time Off request on Wednesday (extra hours), Observe the hours are from 07:30-16:15. - Change the request date to Monday, Observe the hours will still be from 07:30-16:15 not 07:30-16:30. Cause: This was introduced by this commit https://github.com/odoo/odoo/commit/acc03a1d890d2e8bd39e1506475df4c917697111 https://github.com/odoo/odoo/blob/3592b7826ca0c7c30511705e3282dd2c39a901ac/addons/hr_holidays/models/hr_leave.py#L255-L273 preserves non-empty `request_hour_from/request_hour_to` on hourly requests, but no date onchange refreshes those values when they were calendar defaults for the previous date, so it skipped recomputing `request_hour_from/request_hour_to` whenever `request_unit_hours` was set and both hour fields already had values, treating auto filled schedule hours as manual values. Solution: Add a request date onchange to recompute hourly defaults from the new date schedule, while preserving manually selected hours when they differ from the previous calendar default. opw-6259899 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271582
Clicking a Unit Cost in the stock report opens the Unit Cost History of that product. The action filters on `active_id`, which the cost cell fills with the id of the row that was clicked. That value was overwritten: the cell context was merged first and the context of the running action last, so the latter won. When the list comes from "Inventory at Date", that context carries the id of the `stock.quantity.history` record the wizard just created, which is not a product id at all. The history
Original PR description
Clicking a Unit Cost in the stock report opens the Unit Cost History of that product. The action filters on `active_id`, which the cost cell fills with the id of the row that was clicked. That value was overwritten: the cell context was merged first and the context of the running action last, so the latter won. When the list comes from "Inventory at Date", that context carries the id of the `stock.quantity.history` record the wizard just created, which is not a product id at all. The history then opens on whichever product happens to carry that id, and stays empty when none does. Steps to reproduce: - Inventory > Reporting > Stock, click a Unit Cost -> the history of that product opens, as expected - go back, click "Inventory at Date" and confirm - click that same Unit Cost -> another product's history opens, or an empty list opw-6391778 Forward-Port-Of: odoo/odoo#279116
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users & Companies > Companies and create two companies c1 and c2 3. Go to Website > Configuration > Websites and create two websites w1 with company c1 and w2 with company c2 4. Change the order of the websites so that w1 is at the top 5. Go to Website > eCommerce > Pricelists and create a pricelist pl
Original PR description
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users &…
With the Shared Customer Account setting enabled, a user created in c1 cannot access the shop in the website of c2 Steps to reproduce: 1. Install eCommerce and Contacts 2. Go to Settings > Users & Companies > Companies and create two companies c1 and c2 3. Go to Website > Configuration > Websites and create two websites w1 with company c1 and w2 with company c2 4. Change the order of the websites so that w1 is at the top 5. Go to Website > eCommerce > Pricelists and create a pricelist pl1 in c1 assigned to w1 and pl2 in c2 assigned to w2 6. In an incognito tab, go to w1 and create a new account 7. As admin, go to Website > Configuration > Websites and change the order of the websites so that w2 is at the top 8. In an incognito tab, connect with the previously created account and go to the shop 9. An error is thrown (This error only happens when geoip works, i.e. when `_get_geoip_country_code` returns something) Issue: When geoip returns a country code, we search through all the pricelists available for that country code but some of them can be restricted to a company which raises an access error. We need to be able to access them in order to filter the ones that are not available on the current website Solution: Access all pricelists with sudo, they will be filtered out with `_is_available_on_website` opw-3574089 Forward-Port-Of: odoo/odoo#268863
**Issue:** `test_mail_template_dynamic_placeholder_tour` tour is failing sometimes with the following error: `Tour mail_template_dynamic_field_tour → Step Click on contact (trigger: div[name="model_id"] .ui-autocomplete). TypeError: Cannot read properties of undefined (reading 'click')` **Cause:** It happens that the element is not loaded yet after the delay and clicking on an undefined element triggers the error. **Solution:** Make sure to only click on the element when it's ready.
Original PR description
**Issue:** `test_mail_template_dynamic_placeholder_tour` tour is failing sometimes with the following error: `Tour mail_template_dynamic_field_tour → Step Click on contact (trigger: div[name="model_id"] .ui-autocomplete). TypeError: Cannot read properties of undefined (reading 'click')` **Cause:** It happens that the element is not loaded yet after the delay and clicking on an undefined element triggers the error. **Solution:** Make sure to only click on the element when it's ready. runbot-223306 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278983 Forward-Port-Of: odoo/odoo#277954
Preparation printing from mobile self ordering was made by sending a notification in the bus to the PoS. This logic was removed in odoo/odoo#265569, we reintroduce it to allow printing again.
Original PR description
Preparation printing from mobile self ordering was made by sending a notification in the bus to the PoS. This logic was removed in odoo/odoo#265569, we reintroduce it to allow printing again.
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment - Click on the payment method link Traceback: OwlError: The following error occurred in onWillStart: "Cannot find key "pos_payment_provider_cards" in the "view_widgets" registry" Backend views opened from within the PoS UI (order details dialog, drill-down on many2one links, ...) share t
Original PR description
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment…
Steps to reproduce: - Open any PoS session - Click on Orders and filter by "Paid" orders - Select an order and click on "Details" - Open the "Payments" tab and click on the "View" button of a payment - Click on the payment method link Traceback: OwlError: The following error occurred in onWillStart: "Cannot find key "pos_payment_provider_cards" in the "view_widgets" registry" Backend views opened from within the PoS UI (order details dialog, drill-down on many2one links, ...) share their arch with the backend, but `point_of_sale._assets_pos` excludes everything under `static/src/backend/`, so widgets defined there (e.g. `pos_payment_provider_cards`, `lna_checklist`, `point_of_sale_test_epos`) are never registered in the PoS UI. Unlike missing field widgets, which fall back to the default widget with a warning, an unknown `<widget>` node makes the whole view crash since `Widget.parseWidgetNode` reads the registry without a fallback. Those widgets are backend configuration helpers that are irrelevant in a PoS session, so instead of bundling each of them (and any future one) in the PoS assets, patch `Widget.parseWidgetNode` in the PoS bundle to skip unknown widgets with a warning, like missing field widgets do. This covers the form, list and kanban arch parsers at once. opw-6382156 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276912
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: - "Component" - "Final" with a bom containing "Component" and tracked by Serial number - "Setup" with a bom containing "Final" * Create and confirm a MO for "Setup" - assign the serial number "PROD" to "Final" * Produce "Setup" * Create and confirm a MO for "Final" * Generate a seria
Original PR description
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: -…
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: - "Component" - "Final" with a bom containing "Component" and tracked by Serial number - "Setup" with a bom containing "Final" * Create and confirm a MO for "Setup" - assign the serial number "PROD" to "Final" * Produce "Setup" * Create and confirm a MO for "Final" * Generate a serial number * Clear the serial number * Generate a new serial number * Produce "Final" -> In Product Moves you can see that the serial number assign was "PROD" **Observation** First when creating the MO, it will create a stock move for "final" and create a stock move line without assigning any quant. action_confirm -> _action_assign https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_move.py#L1643-L1646 In _action_assign it will bypass_reservation since the location is "production": https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_move.py#L1948 https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_location.py#L411-L413 and create the sml: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/stock/models/stock_move.py#L2048 When adding the Serial number it will be added to lot_producing_ids, set qty_producing and call set_qty_producing ->_set_quantity_done -> _set_quantity_done_prepare_vals: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/mrp/models/mrp_production.py#L1593-L1597 In set_qty_producing->_set_quantity_done ->_set_quantity_done_prepare_vals nothing will be done since there already is a stock move line with the right quantity: https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/stock/models/stock_move.py#L2368-L2371 Second when clearing the Serial number it will call action_clear_lot_producing_ids, where it will - Erase the lot from lot_producing_ids - Set qty_producing to 0 - and call _set_qty_producing _set_qty_producing -> _set_quantity_done -> _set_quantity_done_prepare_vals: where it will erase the stock move line since it's new quantity is 0: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/stock/models/stock_move.py#L2353-L2355 Lastly this means that when add in the new lot, it will not already have a stock move line, and it will create a new stock move line based on available quants: https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/stock/models/stock_move.py#L2392-L2402 The lot_ids on the moves is supposed the get assigned when we produce the product: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/mrp/models/mrp_production.py#L1911-L1913 opw-6240857 Forward-Port-Of: odoo/odoo#268542
When an image is start-aligned, if a list is defined after it, its bullets/numbers/checkboxes are rendered on top of the image. This commit makes the bullets rendered after the image. Steps to reproduce: - Edit a website page - Drop a text page - Insert an image with `/image` - Align image to the left - Insert a bullet list or a numbered list or a checkbox list with some indented entries => Some bullets were rendered on top of the image Additionally, the start-align is neutral
Original PR description
When an image is start-aligned, if a list is defined after it, its bullets/numbers/checkboxes are rendered on top of the image. This commit makes the bullets rendered after the image. Steps to reproduce: - Edit a website page - Drop a text page - Insert an image with `/image` - Align image to the left - Insert a bullet list or a numbered list or a checkbox list with some indented entries => Some bullets were rendered on top of the image Additionally, the start-align is neutralized inside list lines because other approaches do not provide a satisfactory layout - and break further situations. task-6116437 Forward-Port-Of: odoo/odoo#260325
Description of the issue this commit addresses: The settlement tour expects an invoice named with the year 2026. On time-shifted test instances, invoices use a later year, so the tour cannot find the invoice and fails at the settlement selection step. --- Desired behavior after this commit is merged: This commit matches settlement invoices using the stable journal prefix, so the tour works regardless of the year in which it runs. --- runbot-[242206](https://runbot.odoo.com/odoo
Original PR description
Description of the issue this commit addresses: The settlement tour expects an invoice named with the year 2026. On time-shifted test instances, invoices use a later year, so the tour cannot find the invoice and fails at the settlement selection step. --- Desired behavior after this commit is merged: This commit matches settlement invoices using the stable journal prefix, so the tour works regardless of the year in which it runs. --- runbot-[242206](https://runbot.odoo.com/odoo/error/242206) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278573
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people,
Original PR description
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but…
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people, since they would access the page so often, google automatically fill up the url when they type odoo to odoo/web/login This commit aims to introduce a link to the home page that will be displayed in the warning message. This way cusotmers can get to the home page, and we will hopefully stop the support tickets this has created opw-6331783 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
The state_id field was not cleared when editing an address and switching to a country without states — the state selector reset visually, but the stale state_id was still saved to the backend. Steps to reproduce: 1. Add a product to the cart. 2. Go to checkout and edit the address, selecting a country that has states. 3. Edit the address again, now selecting a country without states. 4. Save and check the contact in the backend: state_id still holds the state from the previo
Original PR description
The state_id field was not cleared when editing an address and switching to a country without states — the state selector reset visually, but the stale state_id was still saved to the backend. Steps to reproduce: 1. Add a product to the cart. 2. Go to checkout and edit the address, selecting a country that has states. 3. Edit the address again, now selecting a country without states. 4. Save and check the contact in the backend: state_id still holds the state from the previous country. Solution: reset the state_id select options for the new country. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278660 Forward-Port-Of: odoo/odoo#278125
Steps to reproduce: - Edit a page. - Drop a carousel snippet like s_quotes_carousel - Click "Add Slide" with the browser console open(for concrete race condition) => Traceback: TypeError: Cannot read properties of null (reading 'classList') Cause: `slide()` used the editor window's `Carousel` instead of the iframe's. This created a second Carousel instance for the same element. Both instances updated the indicators at the same time, causing one to remove the active indicator before the
Original PR description
Steps to reproduce: - Edit a page. - Drop a carousel snippet like s_quotes_carousel - Click "Add Slide" with the browser console open(for concrete race condition) => Traceback: TypeError: Cannot read properties of null (reading 'classList') Cause: `slide()` used the editor window's `Carousel` instead of the iframe's. This created a second Carousel instance for the same element. Both instances updated the indicators at the same time, causing one to remove the active indicator before the other tried to use it, leading to the traceback. Fix: Use `this.window.Carousel` so the iframe's existing Carousel instance is reused instead of creating a second one. task-6084484 Forward-Port-Of: odoo/odoo#279117 Forward-Port-Of: odoo/odoo#275903
### Issue before this commit: 1. When generating a FatturaPA XML for a self-invoice (reverse charge / autofattura, e.g. TD17-TD19) with the "Reference" (ref) field filled in, the supplier's invoice number was placed under <DatiOrdineAcquisto> instead of <DatiFattureCollegate>. 2. When a credit note was generated from a vendor bill, the <IdDocumento> in <DatiFattureCollegate> contained Odoo's internal document number (e.g. BILL/2026/07/0002) instead of the actual reference of the invoice rece
Original PR description
### Issue before this commit: 1. When generating a FatturaPA XML for a self-invoice (reverse charge / autofattura, e.g. TD17-TD19) with the "Reference" (ref) field filled in, the supplier's invoice…
### Issue before this commit: 1. When generating a FatturaPA XML for a self-invoice (reverse charge / autofattura, e.g. TD17-TD19) with the "Reference" (ref) field filled in, the supplier's invoice number was placed under <DatiOrdineAcquisto> instead of <DatiFattureCollegate>. 2. When a credit note was generated from a vendor bill, the <IdDocumento> in <DatiFattureCollegate> contained Odoo's internal document number (e.g. BILL/2026/07/0002) instead of the actual reference of the invoice received from the supplier (ref). ### Steps to reproduce the issue: ISSUE 1: 1. Download Accounting and l10n_it 2. Go to Vendor -> Bills 3. Create a bill with: 1. Italian company as vendor 2. Product with tax 22% S RC 3. Bill reference filled (ex. FT00001) 4. Send it to SDI, open the XML and see that the tag <IdDocumento> is inside the tag <DatiOrdineAcquisto> while it sohuld be inside <Datifatturecollegate> ISSUE 2: 1. From a bill created click Credit Note 2. Send to SDI again, open the XML and see that the tag <IdDocumento> contains the bill reference created in Odoo while it should take the reference of the original invoice SENT by the vendor ### Cause of the issue: 1. The template's t-elif chain did not distinguish between self-invoices and regular documents, so any value in record.ref was routed to DatiOrdineAcquisto regardless of context. 2. Separately, the linked_moves loop always used linked_move.name to populate <IdDocumento>, which for vendor bills/refunds is Odoo's own sequential number, not the supplier's original invoice number. ### Reason to introduce the fix: 1. For the official FatturaPA Technical Specifications, DatiOrdineAcquisto must only reference a purchase order, while DatiFattureCollegate must reference a related invoice — which is the correct category for the supplier document being integrated in a self-invoice. This is confirmed by the Agenzia delle Entrate documentation: https://www.agenziaentrate.gov.it/portale/documents/d/guest/allegato-a-specifiche-tecniche-vers-1-9 (p.107, chapter Compilazione del documento XML con codice TD17) 2. For credit/debit notes, <IdDocumento> inside <DatiFattureCollegate> must contain the number of the original invoice being referenced/varied, not an internally generated document number, as clarified here: https://www.pa.sm/ticket/kb/faq.php?id=46 opw-6117968 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276523
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#279071 Forward-Port-Of: odoo/odoo#278667
Original PR description
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#279071 Forward-Port-Of: odoo/odoo#278667
Issue: --- `code` is hidden in `payment.method` from without dev mode, which cause an validation error when creating a new payment method. opw-6390285 Forward-Port-Of: odoo/odoo#278671
Original PR description
Issue: --- `code` is hidden in `payment.method` from without dev mode, which cause an validation error when creating a new payment method. opw-6390285 Forward-Port-Of: odoo/odoo#278671
A return coming back from the customer must always decrease the delivered quantity of a sale order line, even when it is not linked to its original delivery (no origin_returned_move_id and its picking has no return_id) These unlinked returns are created through a negative procurement, example: when the ordered quantity is reduced below the delivered one. Steps to reproduce: - Confirm a sale order of 10 and deliver the 10 - Cancel the order and reset it to draft - Reduce the line quantit
Original PR description
A return coming back from the customer must always decrease the delivered quantity of a sale order line, even when it is not linked to its original delivery (no origin_returned_move_id and its picking has no return_id) These unlinked returns are created through a negative procurement, example: when the ordered quantity is reduced below the delivered one. Steps to reproduce: - Confirm a sale order of 10 and deliver the 10 - Cancel the order and reset it to draft - Reduce the line quantity from 10 to 4 - Re-confirm: the pull rule generates a return of 6 with to_refund set but no origin_returned_move_id nor picking.return_id - Validate that return Before: delivered stays at 10. After: delivered is 4. opw-6345628 Forward-Port-Of: odoo/odoo#274399
Issue: --- If a product template has dynamic attributes, some variants might not exist. For those variants, we are showing wrong stock in the website. To reproduce: 1- Create a product with a dynamic attribute and two values. 2- Publish the product and uncheck sell when out-of-stock and check show product when the qty is less than 5. 3- Create a purchase order with qty = 4 for the first value, so a variant is created for it. 4- Go to the website shop. Open the product. 4 available qty i
Original PR description
Issue: --- If a product template has dynamic attributes, some variants might not exist. For those variants, we are showing wrong stock in the website. To reproduce: 1- Create a product with a dynamic attribute and two values. 2- Publish the product and uncheck sell when out-of-stock and check show product when the qty is less than 5. 3- Create a purchase order with qty = 4 for the first value, so a variant is created for it. 4- Go to the website shop. Open the product. 4 available qty in stock is shown for the first variant which is correct. 5- Select 2nd variant. As you see, still 4 available qty is shown which is wrong. As the out-of-stock sale is unchecked, an out-of-stock warning should be shown. Cause and Fix: --- This is due to `isMainProduct` being always False when `product_id` is not set which makes `free_qty` and `out_of_stock` not to be updated. opw-6237602 Forward-Port-Of: odoo/odoo#277259 Forward-Port-Of: odoo/odoo#273104
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal instead of the correct one (Vendor Bills), even though the move_type itself was correct. ### Steps to reproduce the issue: Pre steps: you need to have access to https://iap-services-test.odoo.com/odoo 1. Download Accounting and l10n_it 2. Go to Settings > Companies and set the VAT of IT company
Original PR description
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal…
### Issue before this commit: When importing an electronic invoice from SDI that is failing with an exception, the resulting account.move record was saved in the "Miscellaneous Operations" journal instead of the correct one (Vendor Bills), even though the move_type itself was correct. ### Steps to reproduce the issue: Pre steps: you need to have access to https://iap-services-test.odoo.com/odoo 1. Download Accounting and l10n_it 2. Go to Settings > Companies and set the VAT of IT company the same as the one in the xml 3. Go to Settings > Italian Electronic Invoicing and select Test 4. Go into the code and insert an Exception inside the function _l10n_it_edi_import_invoice after self.move_type = move_type (or create any type of exception from the user interface) 5. Go to IAP service into IT EDI app and see that your company is there as user 6. Click into the record > receive move button > upload your xml > create 7. Go to your DB > Scheduled Actions > filter with IT > IT EDI: Receive invoices from the SdI > Run Manually 8. Go to Journal entries, remove the filter and find your imported bill 9. You can see it was inserted into the Miscellaneous Operations Journal instead of a Vendor Bill Journal ### Cause of the issue: The move is created inside a savepoint context manager, designed so that even if parsing fails, an empty move with the attachment still remains. The problem is that if the exception is raised, the savepoint rollback undoes everything that follows, but the journal was already determined before the correct move_type was known, leaving the move in the wrong default journal. ### Reason to introduce the fix: The fix is needed to ensure that, regardless of where parsing fails, the move's journal is correctly set even if an exception occurs so that it is possible to find the move in the correct section even if not imported correctly. opw-6397712 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279566 Forward-Port-Of: odoo/odoo#278111
Documentation and clarification updates
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representat
Original PR description
Description of the issue/feature this PR addresses: Add the Odoo Corporate Contributor License Agreement for bobco GmbH and list the employees authorized to contribute on the company's behalf. Current behavior before PR: bobco GmbH does not yet have a corporate CLA in the Odoo repository. Desired behavior after PR is merged: The corporate CLA covers the listed bobco GmbH contributors. Approval and signature status: @philipbr explicitly approved the declaration as an authorized representative of bobco GmbH. The signatory line has been finalized as: `Philip Braun philip@braun.tf https://github.com/philipbr` --- The corporate CLA has been signed by Philip Braun, and the PR guidelines at www.odoo.com/submit-pr have been read. Forward-Port-Of: odoo/odoo#279348
Miscellaneous changes
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclus
Original PR description
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclusions from multiple != operators to a single not in. Explain Before: https://explain.dalibo.com/plan/84095dcgfdc158a2 Explain After: https://explain.dalibo.com/plan/ag2abcdf4ge5d5e5 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278739
Backport of [1]. Builder image tests were flaky in full-suite runs because earlier tests left slow requests pending. Bogus snippet thumbnails, obsolete modify_image mock data, and made-up attachment URLs triggered expensive website 404 rendering and starved the browser connection pool. Avoid rendering missing thumbnails, use data URIs or existing static images in fixtures, return the current modify_image response shape, and give the CORS test image explicit dimensions. [1]: https://gith
Original PR description
Backport of [1]. Builder image tests were flaky in full-suite runs because earlier tests left slow requests pending. Bogus snippet thumbnails, obsolete modify_image mock data, and made-up attachment URLs triggered expensive website 404 rendering and starved the browser connection pool. Avoid rendering missing thumbnails, use data URIs or existing static images in fixtures, return the current modify_image response shape, and give the CORS test image explicit dimensions. [1]: https://github.com/odoo/odoo/pull/277424 Forward-Port-Of: odoo/odoo#279314
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266388 Forward-Port-Of: odoo/odoo#279421
Original PR description
The government has held off the `shipToGSTIN` changes until further notice. https://services.gst.gov.in/services/advisoryandreleases/read/668 Hence, this PR reverts those changes. task-6431622 ref - https://github.com/odoo/odoo/pull/266388 Forward-Port-Of: odoo/odoo#279421