Daily updates from Odoo
Tuesday, August 18, 2026
245 changes
11 changes
Resolved issues and error corrections
Fix for the runbot nightly error 944444. bug: The website configurator crashed entirely if one theme snippet's template was missing, instead of just skipping that snippet. steps: Only visible while running `test_01_configurator_translation` fix: Catch MissingError, alongside ValueError, when generating and rendering configurator snippet content. task-6325919
Original PR description
Fix for the runbot nightly error 944444. bug: The website configurator crashed entirely if one theme snippet's template was missing, instead of just skipping that snippet. steps: Only visible while running `test_01_configurator_translation` fix: Catch MissingError, alongside ValueError, when generating and rendering configurator snippet content. task-6325919
Prior to this commit, the call debrief timeline was not properly adapted for RTL layouts. The playhead and timestamp were positioned incorrectly, making the component unusable in RTL. This commit forces the timeline to always render in LTR, as it represents the physical progression of time moving forward. task-6445011 Requires: - https://github.com/odoo/enterprise/pull/127038 | Before | After | |--------|--------| | <img width="1920" height="698" alt="image" src="https://github.com/
Original PR description
Prior to this commit, the call debrief timeline was not properly adapted for RTL layouts. The playhead and timestamp were positioned incorrectly, making the component unusable in RTL. This commit…
Prior to this commit, the call debrief timeline was not properly adapted for RTL layouts. The playhead and timestamp were positioned incorrectly, making the component unusable in RTL. This commit forces the timeline to always render in LTR, as it represents the physical progression of time moving forward. task-6445011 Requires: - https://github.com/odoo/enterprise/pull/127038 | Before | After | |--------|--------| | <img width="1920" height="698" alt="image" src="https://github.com/user-attachments/assets/780f6e83-b67d-44bc-8b00-8e92048ff13b" /> | <img width="1390" height="463" alt="Screenshot 2026-08-11 at 08 51 00" src="https://github.com/user-attachments/assets/8a2a833c-2164-40ed-a4c7-006b7ca5bec4" /> | | <img width="1385" height="418" alt="Screenshot 2026-08-04 at 15 02 05" src="https://github.com/user-attachments/assets/f0c75f29-e459-4ee7-976d-3674ae76ff81" /> | <img width="1384" height="479" alt="Screenshot 2026-08-11 at 08 51 22" src="https://github.com/user-attachments/assets/f60b98c5-5a33-4d01-8521-0f2f3bdd6424" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by some incompatibility between wkhtmltopdf and d-flex, adding `col` to the product name container forces it to respect column boundaries. This commit also adds `text-break` as having a long uninterupded string in the description would end up stretching the column and making the next ones disapear
Original PR description
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by…
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by some incompatibility between wkhtmltopdf and d-flex, adding `col` to the product name container forces it to respect column boundaries. This commit also adds `text-break` as having a long uninterupded string in the description would end up stretching the column and making the next ones disapear. <img width="811" height="266" alt="image" src="https://github.com/user-attachments/assets/90043c88-d03f-4324-9935-e669f6a256ab" /> <img width="964" height="431" alt="image" src="https://github.com/user-attachments/assets/2b8e8a6c-6fd5-4813-8160-d94bbb5490d1" /> ### Steps to reproduce: - Enable Display Product Images in the setting - Create a product with an image - Create a quotation with said product and add a description that is long enough to break to the next line - Print said quotation - You will notice that before the line breaks it will overflow to the next column (you might need to tweak the description a bit by removing or adding a few lines) opw-6367076 Forward-Port-Of: odoo/odoo#275978
Improves UX by deselecting when clicking the header checkbox in list views instead of selecting all. WHY: Fits the UX of almost all other software and saves one click :) Since @34b9af762fa2, the header checkbox of a list view renders in its indeterminate state ([-]) when part of the displayed records are selected. When doing that feature, we thought about the "escape" case to deselect all, but not the click header checkbox case. This PR fixes that. task-6237965
Original PR description
Improves UX by deselecting when clicking the header checkbox in list views instead of selecting all. WHY: Fits the UX of almost all other software and saves one click :) Since @34b9af762fa2, the header checkbox of a list view renders in its indeterminate state ([-]) when part of the displayed records are selected. When doing that feature, we thought about the "escape" case to deselect all, but not the click header checkbox case. This PR fixes that. task-6237965
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls `willOpenRecordInDialog()`, which defaults to `record.save()`. For a new leave request, this triggered `hr.leave.create()`'s validation logic, auto-confirming (or even auto-approving) the request before the user had finished the wizard. This premature save was also the root cause of two related bugs,
Original PR description
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls…
Clicking the internal-link arrow on `work_entry_type_id` (Time Off Type) implicitly saved the `hr.leave` record before opening the related form dialog, since `Many2One.openRecordInDialog()` calls `willOpenRecordInDialog()`, which defaults to `record.save()`. For a new leave request, this triggered `hr.leave.create()`'s validation logic, auto-confirming (or even auto-approving) the request before the user had finished the wizard. This premature save was also the root cause of two related bugs, both fixed as a side effect: closing the Time Type dialog threw `TypeError: Cannot read properties of undefined (reading 'focus')` (the save re-rendered the parent, leaving `Many2One`'s `onClose` pointing at a stale component), and that crash aborted the promise chain before it could reload the calendar, leaving a newly-created leave request missing from view until a manual refresh. Adds a `many2one_no_save` field widget overriding `willOpenRecordInDialog` to skip the save, applied to `work_entry_type_id` on the base `hr_leave_view_form` so all inheriting views are covered. task-6452848
Currently, an error occurs when updating the quantity of an SOL in the portal. **Steps to Reproduce:** - Install the `sale_management` module. - Go to `Settings` and enable `Pricelists` under Pricing. - Go to `Sales` > `Orders` > `Orders` and create a `sale order`. - Add an `order line` of type `Section`, click the `three-dot` menu on the line, and click `Set Optional`. - Add another line using `Add a line` and enter only the `description` in that line. - Save the `order` and clic
Original PR description
Currently, an error occurs when updating the quantity of an SOL in the portal. **Steps to Reproduce:** - Install the `sale_management` module. - Go to `Settings` and enable `Pricelists` under…
Currently, an error occurs when updating the quantity of an SOL in the portal. **Steps to Reproduce:** - Install the `sale_management` module. - Go to `Settings` and enable `Pricelists` under Pricing. - Go to `Sales` > `Orders` > `Orders` and create a `sale order`. - Add an `order line` of type `Section`, click the `three-dot` menu on the line, and click `Set Optional`. - Add another line using `Add a line` and enter only the `description` in that line. - Save the `order` and click `Preview`. - `Increase` the quantity of the line using the + icon. `ValueError: Expected singleton: product.product()` After [recent commit], support for productless Sale Order Lines was added, allowing users to create quotation/invoice lines directly from descriptions without requiring a product. After [this commit], when updating the quantity of a productless SOL in the portal, the price is updated based on the pricelist [1]. While getting the pricelist price [2] for the SOL, the product is ensured on the SOL, which raises the error [3] because the SOL does not have a product. This commit ensures that the unit price is updated based on the pricelist only if the line contains a product. [recent commit]: https://github.com/odoo/odoo/commit/d069ce59e28fda2bc25fb89fd01ee7b988a30fa0 [this commit]: https://github.com/odoo/odoo/commit/86d40fe5c5ad32af0ceca7cd384b96a8a2f4adc3 [1]- https://github.com/odoo/odoo/blob/e940a655aba06adc784008b72a3917170fdb3dd0/addons/sale_management/controllers/portal.py#L68-L69 [2]- https://github.com/odoo/odoo/blob/e940a655aba06adc784008b72a3917170fdb3dd0/addons/sale/models/sale_order_line.py#L783 [3]- https://github.com/odoo/odoo/blob/e940a655aba06adc784008b72a3917170fdb3dd0/addons/sale/models/sale_order_line.py#L801 sentry-7665145989 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was mi
Original PR description
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was missing from the report template if self-billing is enabled. ***Fix*:** * Add the missing condition so that the self-billing header is displayed when **Self Billing** is enabled on the journal. * For reference, here is the [Document](https://www.gesetze-im-internet.de/ustg_1980/__14.html) link. Ticket [link](https://www.odoo.com/odoo/project.task/6281066) opw-6281066 Forward-Port-Of: odoo/odoo#282664 Forward-Port-Of: odoo/odoo#272857
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines (e.g. 160.00). 4. Switch the document tax mode from "Tax Excl." to "Tax Incl." using the toggle at the top of the Order Lines tab. **Issue:** - After switching to "Tax Incl." mode, the total on the sale order is higher than the previous untaxed amount (e.g. shows 266.00 instead of the 160.00).
Original PR description
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines…
**Steps to reproduce:** 1. Install the sale module with demo data. 2. Open a sale order and add a combo product (e.g. "Office Combo"). 3. Note the displayed untaxed amount on the combo item lines (e.g. 160.00). 4. Switch the document tax mode from "Tax Excl." to "Tax Incl." using the toggle at the top of the Order Lines tab. **Issue:** - After switching to "Tax Incl." mode, the total on the sale order is higher than the previous untaxed amount (e.g. shows 266.00 instead of the 160.00). - The same switch works correctly on regular (non-combo) product lines **Expected behavior:** - the new total should equal the previous untaxed amount. **Why this happens:** - `_onchange_order_line` is triggered on every `order_line` change, including when switching `document_tax_mode` causes `price_subtotal` to update on existing lines. - The unconditional write to `product_uom_qty` and `discount` on all combo item lines was calling '_compute_price_unit` even when neither value had changed. - `_compute_price_unit` then called `_reset_price_unit` under the new `document_tax_mode`, which re-calculated the stored `price_unit` instead of leaving it untouched for `_compute_amount` to reinterpret correctly. **Fix:** - Only sync `product_uom_qty` and `discount` to the combo item lines whose current values actually differ from the parent line. When no value has changed, no write occurs, so `_compute_price_unit` is not called. opw-6427963
Steps: - Install l10n_ma module. - Go to Address page in portal. - Select Morocco country. - Set any random invalid value for ICE input. Issue: - It wont allow to save address and will not give any error or suggestion instead it raises validation error in logger. Cause: - Since recent [fix](https://github.com/odoo/odoo/pull/271969) invalid additional_identifier raises an error for invalid values and in portal we can't display those error directly. Fix: - Validate `additional_iden
Original PR description
Steps: - Install l10n_ma module. - Go to Address page in portal. - Select Morocco country. - Set any random invalid value for ICE input. Issue: - It wont allow to save address and will not give any error or suggestion instead it raises validation error in logger. Cause: - Since recent [fix](https://github.com/odoo/odoo/pull/271969) invalid additional_identifier raises an error for invalid values and in portal we can't display those error directly. Fix: - Validate `additional_identifier` in validate address values and and mark those identifier as invalid field for invalid values to give proper error message and not raise validation error. Also skip `_validate_identifier` for `no_vat_validation` context in creation since we already validate those identifier values.
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
Original PR description
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
11 changes
Resolved issues and error corrections
Repro steps: 1) Create 2 accounts in 2 different companies, both with no code 2) Merge the 2 accounts 3) On the merged account, attempt to a) add a code b) unmerge the accounts Problems: a) psycopg2.errors.InvalidParameterValue: cannot call jsonb_each on a non-object b) cannot delete from scalar Root cause: json.dumps(code_by_company) returns 'null' when code_by_company is None. This results in code_store being stored as JSON null instead of SQL null resulting in the errors men
Original PR description
Repro steps: 1) Create 2 accounts in 2 different companies, both with no code 2) Merge the 2 accounts 3) On the merged account, attempt to a) add a code b) unmerge the accounts Problems: a) psycopg2.errors.InvalidParameterValue: cannot call jsonb_each on a non-object b) cannot delete from scalar Root cause: json.dumps(code_by_company) returns 'null' when code_by_company is None. This results in code_store being stored as JSON null instead of SQL null resulting in the errors mentioned above because the field is expected to hold SQL NULL when empty instead of JSON null. task-6397515
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing
Original PR description
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax…
### Issue before this commit: When generating an electronic invoice (e.g., ZUGFeRD/Factur-X) with a 0% tax from a non-EEA supplier (e.g., Switzerland) to an EEA customer (e.g., Germany), the XML tax <ram:CategoryCode> is incorrectly set to 'E' (Exempt) instead of 'G' (Export). ### Steps to reproduce the issue: 1. Download Accounting and l10n_ch 2. Set the VAT for the CH company 3. Create an invoice for a German customer with 0% tax setted (for which you have to set as electronic invoicing the ZUGFeRD template into the Accounting tab of his contact) 4. Send it and see that the tag <ram:CategoryCode> is setted as E instead of G ### Cause of the issue: The logic assigning the 'G' and 'K' tax category codes was only triggered if the supplier was located within the EEA. If the supplier was outside the EEA, the code bypassed this block entirely and fell back to the default 'E' code for 0% taxes. ### Reason to introduce the fix: Update the condition to trigger when either the supplier or the customer is in the EEA. This ensures that cross-border transactions involving at least one EEA party correctly evaluate and apply the 'G' (Export outside the EU) category code. Also the case supplier not in eea with VAT filled in + customer in eea + RC tax with amount != 0 is fixed now (letter G reported instead of S). ### Documentation: [eInvoicing technical guidance document_v1.pdf](https://github.com/user-attachments/files/30831749/eInvoicing.technical.guidance.document_v1.pdf) opw-6407399 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282497 Forward-Port-Of: odoo/odoo#281245
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xm
Original PR description
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm…
**Steps to reproduce:** 1. Install Sales and payment_authorize modules 2. Enable "Online Payment" in the settings and Configure the payment method to be Authorize.net 3. Create a sale order, confirm it and create the invoice 4. Pay the invoice with an eCheck (ACH) payment method through the Authorize.net provider 5. Wait for the payment to be settled by Authorize.net (_around 24 hours_) 6. Initiate a refund of the payment **Issue:** The refund fails with error `E00003: "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XX is invalid according to its datatype 'String' - The actual length is less than the MinLength value` **Expected behavior:** The refund should be processed successfully regardless of whether the original payment was made by credit card or eCheck (ACH) **Why this happens:** - The `refund()` method in `AuthorizeAPI` builds the refund request using a `creditCard` payment payload - When the original transaction was an ACH/eCheck payment, the `creditCard` key is absent from the transaction details returned by Authorize.net - The resulting request is rejected by Authorize.net because it does not satisfy the minimum length constraint for `cardNumber` **Fix:** - Detects whether the original payment used `creditCard` or `bankAccount` from the transaction details and build the appropriate payload according to Authorize.net API documentation: https://developer.authorize.net/api/reference/index.html#payment-transactions-credit-a-bank-account opw-6359726 Forward-Port-Of: odoo/odoo#277742
Steps to reproduce: - Install employees and attendance app - Make sure there are 2 companies - Make user's employee record for Company B, but not A - Make company A the default company for user - Enable "attendances from backend" setting - Click on the attendance dot (systray) Current Behavior: The dot disappears and you can't check in Expected Behavior: You are able to check in Other bug scenario: If you have employee records in both Company A and Company B, you can check in.
Original PR description
Steps to reproduce: - Install employees and attendance app - Make sure there are 2 companies - Make user's employee record for Company B, but not A - Make company A the default company for user - Enable "attendances from backend" setting - Click on the attendance dot (systray) Current Behavior: The dot disappears and you can't check in Expected Behavior: You are able to check in Other bug scenario: If you have employee records in both Company A and Company B, you can check in. However, you can never check in for Company B as the default company is always selected in the server code opw-6392301 Forward-Port-Of: odoo/odoo#280566 Forward-Port-Of: odoo/odoo#278377
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was mi
Original PR description
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was missing from the report template if self-billing is enabled. ***Fix*:** * Add the missing condition so that the self-billing header is displayed when **Self Billing** is enabled on the journal. * For reference, here is the [Document](https://www.gesetze-im-internet.de/ustg_1980/__14.html) link. Ticket [link](https://www.odoo.com/odoo/project.task/6281066) opw-6281066 Forward-Port-Of: odoo/odoo#282664 Forward-Port-Of: odoo/odoo#272857
### Steps to reproduce: - Create a product with a bom and 2 operations - Create an MO for 1 unit of that product - Confirm the MO - On the bom, delete the second operation and modify the first operation on anything else than the company, name or workcenter - Go back to the MO, click the "Update Bom" button > The second operation is not unlinked and the first operation is not updated ### Cause of the issue: The `action_update_bom` updates the move raws and operations of the MO via t
Original PR description
### Steps to reproduce: - Create a product with a bom and 2 operations - Create an MO for 1 unit of that product - Confirm the MO - On the bom, delete the second operation and modify the first…
### Steps to reproduce: - Create a product with a bom and 2 operations - Create an MO for 1 unit of that product - Confirm the MO - On the bom, delete the second operation and modify the first operation on anything else than the company, name or workcenter - Go back to the MO, click the "Update Bom" button > The second operation is not unlinked and the first operation is not updated ### Cause of the issue: The `action_update_bom` updates the move raws and operations of the MO via the `_link_bom`: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L1214-L1218 For draft MO's all the work of these updates is done via the compute methods and by deleting all the records unrelevant to the new bom: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2603-L2626 And, in that case all the workorders that are not linked to an operation of the bom are expected to be deleted. However, when the MO is not in draft, the update of operations is expected to be performed here: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2647-L2664 However, since the operation of the bom has been deleted, the workorder that is expected to be deleted is not linked to any operation and hence does not satisfy the condition to be deleted: https://github.com/odoo/odoo/blob/f66614193cce18f5a3298d03ce7e5f29d54f07e9/addons/mrp/models/mrp_production.py#L2663-L2664 Concerning the non update of operations, it happens because the MO's operation are only updated on the three fields: `company_id`, `workcenter_id`, `name`: https://github.com/odoo/odoo/blob/31df5033e31c193b4576ef37dfbc5fc683817bc5/addons/mrp/models/mrp_production.py#L2647-L2664 https://github.com/odoo/odoo/blob/31df5033e31c193b4576ef37dfbc5fc683817bc5/addons/mrp/models/mrp_production.py#L2628-L2629 However, many other changes can and are actually relevant. ### Note: Prior to commit 80e6ed658fb43584bc2fad673ca40d9af6cf0ab6 operations were archived on boms rather than deleted: https://github.com/odoo/odoo/blob/4a5270218fe6fd7d30edb6d684b3340dc7423bab/addons/mrp/views/mrp_routing_views.xml#L53-L55 As such they would still be linked to an operation (but unrelated to the present values of the bom) and hence would fall into the condition of being unlinked from the MO. Since the bom operations are no longer archived there is no way to determine if an operation used to be linked to a bom and we therefore need to chose between deleting all operations unrelated to the present bom or to keep them all (when the MO has been confirmed). Enterprise: https://github.com/odoo/enterprise/pull/120709 opw-6285878 opw-6261738 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280803 Forward-Port-Of: odoo/odoo#269747
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids remain unchanged after the upgrade and do not reflect the modifications introduced in [1]. The tax definitions are loaded from CSV data and don't happen during upgrade or module update it did through try_loading". Since the account tags already exist in upgraded databases, the changes
Original PR description
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids…
**Step to Reproduce:** 1. Create a database in 18.0 with `l10n_mt` installed. 2. Select the Malta chart template (COA). 3. Upgrade the database to 19.0. 4. Verify the tax grids. **Issue:** Tax grids remain unchanged after the upgrade and do not reflect the modifications introduced in [1]. The tax definitions are loaded from CSV data and don't happen during upgrade or module update it did through try_loading". Since the account tags already exist in upgraded databases, the changes are not applied during module loading and the updated grid assignments are not assigned to taxes. **Fix:** Apply the grid update directly through SQL during the upgrade or module update. The change is limited to tax grid assignments and does not require a full tax reload using ``try_loading`` or ``load_data``. **Before fix:** <img width="1458" height="724" alt="image" src="https://github.com/user-attachments/assets/eaac5e3f-d551-4ec0-b282-bb39a50438f9" /> **After fix:** <img width="1240" height="583" alt="image" src="https://github.com/user-attachments/assets/74409c53-dce0-45b2-a6b5-e60f5c2d826d" /> Note: why this fix is needed because existing upgrade script do update move line grid but still tax have the old grid which is weird and will cause issue when journal entry will create. [1]: https://github.com/odoo/odoo/pull/254894/changes/8921186850e31c53072d49a5dc760192f3edb902 opw-6325845 upg-4391393 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#272038
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This causes the text to get cut off, making the exact number unreadable. Solution: This commit updates the badge container to properly accommodate larger numbers. The text now fits entirely within the badge without overflowing, ensuring the hidden tag count remains fully readable. Steps to reproduce (
Original PR description
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This…
Problem: When using the many2many_avatar_user widget (such as in the Live Chat app), the badge displaying the number of hidden tags overflows if the count reaches double digits (e.g., "+10"). This causes the text to get cut off, making the exact number unreadable. Solution: This commit updates the badge container to properly accommodate larger numbers. The text now fits entirely within the badge without overflowing, ensuring the hidden tag count remains fully readable. Steps to reproduce (runbot v19.3): 1. Open the Live Chat app (or any view using the many2many_avatar_user widget). 2. Add enough agents to a session so the remaining count hits double digits (10 or more). 3. Observe that the badge showing the remaining agent count (e.g., "+10") overflows the badge container, cutting off the text and making it unreadable. opw-6453976 <img width="2655" height="1111" alt="avatar_tag_193_before" src="https://github.com/user-attachments/assets/9c31007d-5300-4bb7-a703-01a13b5bdd10" /> <img width="2655" height="1112" alt="avatar_tag_193_after" src="https://github.com/user-attachments/assets/7b2a4074-3738-4a6c-9649-f6652601f3f3" />
Previously, the live chat statistics section did not use the available width on mobile devices, leaving unnecessary empty space and resulting in an awkward layout. This PR makes the statistics cards take the full available width on mobile, providing a cleaner and more consistent interface. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="372" height="805" alt="image" src="https://github.com/user-attachments/assets/6934927b-f744-4c93-b63e-1f49ecd33004" /> </td
Original PR description
Previously, the live chat statistics section did not use the available width on mobile devices, leaving unnecessary empty space and resulting in an awkward layout. This PR makes the statistics cards take the full available width on mobile, providing a cleaner and more consistent interface. <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> <img width="372" height="805" alt="image" src="https://github.com/user-attachments/assets/6934927b-f744-4c93-b63e-1f49ecd33004" /> </td> <td> <img width="382" height="734" alt="image" src="https://github.com/user-attachments/assets/24f8b7e4-9fe7-4fa0-bf64-5d7917623830" /> </td> </tr> </table> --- Task ID - 6372787
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
Original PR description
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
7 changes
Resolved issues and error corrections
When using multiple devices sharing draft orders, a race condition can happen where one device reuses another device's empty synced draft order. This leads to duplicate UUIDs, which triggers automatic order merging in `sync_from_ui` on the server and clears the table association. To prevent this: - Filter out synced orders (`!order.isSynced`) in `getEmptyOrder()`, `createOrderIfNeeded()`, and `setTable()` when looking for reusable empty orders. - This ensures each terminal only reuses its o
Original PR description
When using multiple devices sharing draft orders, a race condition can happen where one device reuses another device's empty synced draft order. This leads to duplicate UUIDs, which triggers automatic order merging in `sync_from_ui` on the server and clears the table association. To prevent this: - Filter out synced orders (`!order.isSynced`) in `getEmptyOrder()`, `createOrderIfNeeded()`, and `setTable()` when looking for reusable empty orders. - This ensures each terminal only reuses its own locally created, unsynced empty orders, guaranteeing unique UUIDs per device session. task-id: 6296661 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269551
Steps to reproduce ------------------ 1. Configure a product with a subcontracted BoM and a subcontractor. 2. Create a purchase order of 10 units for that product and confirm it. 3. Receive the 10 units. 4. On the receipt, use "Return for Exchange" on 3 units and validate both the return and the exchange receipt. Issue ----- After the exchange, the 3 units stay in the subcontracting location instead of reaching `WH/Stock`, and the received quantity on the purchase order line stays at 7
Original PR description
Steps to reproduce ------------------ 1. Configure a product with a subcontracted BoM and a subcontractor. 2. Create a purchase order of 10 units for that product and confirm it. 3. Receive the 10…
Steps to reproduce ------------------ 1. Configure a product with a subcontracted BoM and a subcontractor. 2. Create a purchase order of 10 units for that product and confirm it. 3. Receive the 10 units. 4. On the receipt, use "Return for Exchange" on 3 units and validate both the return and the exchange receipt. Issue ----- After the exchange, the 3 units stay in the subcontracting location instead of reaching `WH/Stock`, and the received quantity on the purchase order line stays at 7 instead of 10. `mrp_subcontracting` overrides `_prepare_move_default_values` to force the move `location_dest_id` to the subcontractor location for every `is_subcontract` move: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/mrp_subcontracting/wizard/stock_picking_return.py#L20-L25 That is correct for the return, but the same override also runs for the exchange re-receipt, an `incoming` picking whose destination should be the stock location from `return_type.default_location_dest_id`: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/stock/wizard/stock_picking_return.py#L137-L153 The exchange move then goes from the subcontracting location back to itself, so validating it nets zero and `WH/Stock` never receives the units. Skipping the override when `new_picking.picking_type_id.code` is `incoming` lets the exchange land in stock. The received quantity must also count that receipt. `_should_count_for_quantity_received` only counts `supplier` or `transit` sources: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/stock/models/stock_move.py#L330-L331 so the exchange, sourced from the internal subcontracting location, is skipped while the return still subtracts its quantity. Counting subcontracting-sourced moves: https://github.com/odoo/odoo/blob/d9c06a66356dd9d5a50821b8cde6194967353c18/addons/mrp_subcontracting/models/stock_move.py#L312-L314 restores `qty_received` to 10. opw-6410978 Forward-Port-Of: odoo/odoo#282373 Forward-Port-Of: odoo/odoo#279431
The `/shop` product results and facets use different search fields. In particular, facets search raw `website_description` HTML, causing terms such as `weight` to match CSS like `font-weight` and process far more products than are displayed. Use one shared field list for both paths: - `name` - `variants_default_code` - `description_sale` - `description_ecommerce` Stop searching `default_code`, internal `description`, and raw `website_description`. opw-6391984 --- I c
Original PR description
The `/shop` product results and facets use different search fields. In particular, facets search raw `website_description` HTML, causing terms such as `weight` to match CSS like `font-weight` and process far more products than are displayed. Use one shared field list for both paths: - `name` - `variants_default_code` - `description_sale` - `description_ecommerce` Stop searching `default_code`, internal `description`, and raw `website_description`. opw-6391984 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280720
Before this PR, the o_quick_assign button was not the same size as the o_avatar img which makes it look like it's misaligned when there is a company associated with the job offer. task-6092395 | Before | After | |--------|--------| | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 19 03" src="https://github.com/user-attachments/assets/31b38b78-591d-4c55-b3e8-b3888484f9a1" /> | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 29 40" src="https://github.com/u
Original PR description
Before this PR, the o_quick_assign button was not the same size as the o_avatar img which makes it look like it's misaligned when there is a company associated with the job offer. task-6092395 | Before | After | |--------|--------| | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 19 03" src="https://github.com/user-attachments/assets/31b38b78-591d-4c55-b3e8-b3888484f9a1" /> | <img width="1058" height="705" alt="Screenshot 2026-04-20 at 15 29 40" src="https://github.com/user-attachments/assets/6f78190a-be92-4eeb-9a9f-55e8f247bf1c" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
# How to reproduce - Enable dev mode - In the website editor, add a Video Inner Content to the page - Enable atleast one option that is not "Start at" (e.g. Autoplay) - Click on the Video, and in the Style tab, click on Replace # The problem A traceback is shown # Cause When you replace a video, a pop up appears with the different options associated to that video. These options are rendered with the `VideoOption` component : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac22
Original PR description
# How to reproduce - Enable dev mode - In the website editor, add a Video Inner Content to the page - Enable atleast one option that is not "Start at" (e.g. Autoplay) - Click on the Video, and in the…
# How to reproduce - Enable dev mode - In the website editor, add a Video Inner Content to the page - Enable atleast one option that is not "Start at" (e.g. Autoplay) - Click on the Video, and in the Style tab, click on Replace # The problem A traceback is shown # Cause When you replace a video, a pop up appears with the different options associated to that video. These options are rendered with the `VideoOption` component : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/html_editor/static/src/main/media/media_dialog/video_selector.js#L9 The props for that component accept a `value`, which type has been changed from `Boolean` to `String` in : https://github.com/odoo/odoo/commit/ae894892e048bcdf9c3efcf41b53b44f2fd9e88b The issue is that some option's value are defined as boolean : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/html_editor/static/src/main/media/media_dialog/video_selector.js#L352 So the props validation fail, but only in dev mode : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/web/static/lib/owl/owl.js#L3227-L3231 # Proposed solution When changing the options value in the popup, the trucy values are replaced by "00:00", which is why the traceback only appears when replacing the video : https://github.com/odoo/odoo/blob/46d3fee5812b8406aac2244baa76b0daeef358c2/addons/html_editor/static/src/main/media/media_dialog/video_selector.js#L182-L186 We now use the same trucy represetation in `syncOptionsWithUrl()` opw-6369196 Forward-Port-Of: odoo/odoo#280375 Forward-Port-Of: odoo/odoo#276585
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the
Original PR description
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move…
Before this commit, decreasing the quantity of a move whose move lines are expressed in another unit of measure removed the wrong quantity from the lines, because the two conversions between the move unit and the line unit converted a value to its own unit, hence did nothing. Steps to reproduce: - create a product in Units with available stock - create a delivery for 2 Dozen of it and mark it as todo - in the detailed operations, change the unit of the move line to Units (24) - lower the move quantity from 2 to 1 Dozen The move line ends up with 23 Units instead of 12: the decrease of 1 Dozen is applied as 1 Unit on the line and considered fully processed. The remaining 11 units stay reserved and counted on the transfer. Convert the remaining decrease from the move unit to the line unit when taking it from a line, and the taken quantity back to the move unit when updating the remaining decrease. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278148 Forward-Port-Of: odoo/odoo#276774
`cbc:RoundingAmount` was the sum of `raw_total_excluded` over the non-fixed taxes plus the sum of `raw_tax_amount` over all the taxes, so the base of the line was counted once per non-fixed tax, inflating the line total. `cbc:TaxableAmount` was taken from the tax details of each grouping key, which is the base of that specific tax not the net amount of the line expected by JoFotara. Both amounts are now read from the base line tax details (`raw_total_included` and `raw_total_excluded`), so
Original PR description
`cbc:RoundingAmount` was the sum of `raw_total_excluded` over the non-fixed taxes plus the sum of `raw_tax_amount` over all the taxes, so the base of the line was counted once per non-fixed tax, inflating the line total. `cbc:TaxableAmount` was taken from the tax details of each grouping key, which is the base of that specific tax not the net amount of the line expected by JoFotara. Both amounts are now read from the base line tax details (`raw_total_included` and `raw_total_excluded`), so they describe the line itself regardless of the number of taxes set on it. The document level `cbc:TaxableAmount` keeps using the aggregated tax details. Even tho the problems were hidden because in Jordan, a line wouldn't have more than 1 percent tax + 1 fixed tax, it emerged during the development of the fix in this PR: https://github.com/odoo/odoo/pull/279335 Forward-Port-Of: odoo/odoo#281262
7 changes
Resolved issues and error corrections
*=hr_holidays,im_livechat,mail,test_discuss_full Out-of-office return dates were loaded through the partner's main user's employee_ids. That relation is company-filtered, so users without access to the employee's company did not receive leave_date_to in Discuss until opening the avatar card refreshed the data through another path. This commit fixes this behavior by loading leave_date_to from all employees linked to the partner's main user using sudo and exposing them through the all_e
Original PR description
*=hr_holidays,im_livechat,mail,test_discuss_full Out-of-office return dates were loaded through the partner's main user's employee_ids. That relation is company-filtered, so users without access to the employee's company did not receive leave_date_to in Discuss until opening the avatar card refreshed the data through another path. This commit fixes this behavior by loading leave_date_to from all employees linked to the partner's main user using sudo and exposing them through the all_employee_ids store relation. This makes the out-of-office indication consistently available in the sidebar, member list, and chat banner. task-6095661 Forward-Port-Of: odoo/odoo#263149
Steps to reproduce: - Make sure you have 2 or more languages installed - Install events and website app - For the website, apply the languages you have in settings - Make sure website default language is different from backend language - Create an event - Go to the event's website page through the smart button - Switch the language of the frontend to one that is different from backend - Translate (alter) the description for this language - Click on the outlook icon to download the ics
Original PR description
Steps to reproduce: - Make sure you have 2 or more languages installed - Install events and website app - For the website, apply the languages you have in settings - Make sure website default…
Steps to reproduce: - Make sure you have 2 or more languages installed - Install events and website app - For the website, apply the languages you have in settings - Make sure website default language is different from backend language - Create an event - Go to the event's website page through the smart button - Switch the language of the frontend to one that is different from backend - Translate (alter) the description for this language - Click on the outlook icon to download the ics Current Behavior: The ics will contain a description based on the backend's chosen language Expected Behavior: The ics will contain a description based on the website's chosen language. If there's no website, it will use the browser's language Clarification: The current behavior is confusing for users as they will expect the ics to match the description of the current webpage which is dependent on the frontend's selected language. This current behavior also contradicts the google calendar behavior which grabs the description based on the frontend's selected language. The endpoints for retrieving the ics file now utilize the website=True flag to take advantage of IrHttp._match which will automatically set the context language to be the frontend's rather than the backend language. We want the ics file to be in the frontend language for visual consistency. Also, send_email_reminder function does not require with context for this reason opw-6235320 Forward-Port-Of: odoo/odoo#271968
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was mi
Original PR description
***Steps to reproduce*:** * Install the `l10n_din5008` module. * Set up a German Company and set the fiscal location to Germany. * Select the German company and create a new Purchase Journal. * Enable **Self Billing** for the journal. * Create a vendor bill and print the PDF. ***Observed behavior*:** * The printed document displays the regular vendor bill header instead of the self-billing header. ***Cause*:** * The condition required to display the self-billing header was missing from the report template if self-billing is enabled. ***Fix*:** * Add the missing condition so that the self-billing header is displayed when **Self Billing** is enabled on the journal. * For reference, here is the [Document](https://www.gesetze-im-internet.de/ustg_1980/__14.html) link. Ticket [link](https://www.odoo.com/odoo/project.task/6281066) opw-6281066 Forward-Port-Of: odoo/odoo#282664 Forward-Port-Of: odoo/odoo#272857
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
Be sure that combo product of the current line belong to its combo parent line. Forward-Port-Of: odoo/odoo#281741
Original PR description
Be sure that combo product of the current line belong to its combo parent line. Forward-Port-Of: odoo/odoo#281741
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the fro
Original PR description
Steps to reproduce: 1. In an `en_US` database, install the Arabic (`ar_001`) language and set it as the website's default language. 2. Add a `blog.post` dynamic snippet to a page and select it. 3. Open the snippet options. 4. Notice that the Filter dropdown is displayed in Arabic instead of English. The RPC fetching the available snippet filters targets the `website=True` `/website/snippet/options_filters` route. During the request initialization, website routes inherit the frontend request language (see: `frontend_pre_dispatch()`), so the ORM context lang is set to the website language. As a result, translated fields such as name are read in that language. Force `request.env.user.lang` in the context when fetching the filters since their names should be displayed in the editor's preferred language. task-5979540 Forward-Port-Of: odoo/odoo#280152 Forward-Port-Of: odoo/odoo#275390
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
Original PR description
Fix the function signature of the _reset_peppol_configuration function Step to reproduce: - Install l10n_fr_pdp and register a company on Peppol - When the _peppol_out_of_sync_disconnect_this_database will be called, it will call the _reset_peppol_configuration(soft=True), and since l10n_fr_pdp overrides this function but don't declare the soft parameter, it will raise a TypeError. opw-5728596 Forward-Port-Of: odoo/odoo#282763
3 changes
Resolved issues and error corrections
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two mem
Original PR description
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two members of the channel and typing "Pyn" drops one of them: owl assigns the filtered options one frame before it patches the list, so a click in between looks up index 1 in a list of one option, finds nothing and returns. This commit passes the rendered option to the click handler, keeping the index lookup as a fallback so that the signature stays the same on a stable version. https://runbot.odoo.com/odoo/error/946154 Forward-Port-Of: odoo/odoo#282897
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the forma
Original PR description
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: -…
## Description When a CI/NIE number fails the check digit validation, the raised error suggests `3:402.010-2 or 93:402.010-1 (CI or NIE)` as the expected format. This is misleading for two reasons: - The colon notation comes from Uruware's technical manual and is not how identity card numbers are written in Uruguay: users write `3.402.010-1` or plain digits (`34020101`). Real users facing the error keep reformatting a number whose check digit is simply wrong, believing the problem is the format. - The CI example shown is itself an **invalid** number: the check digit of `3.402.010` is `1`, not `2` — the module's own test suite (`l10n_uy/tests/test_check_vat.py`) uses `3:402.010-2` as an invalid sample. This was reported by an Uruguayan eCommerce user who lost sales because buyers interpreted the message as requiring an unusual format that does not exist in Uruguay. ## Change Replace the examples with valid numbers written in the notations actually used in Uruguay, and clarify that separators are optional — which is exactly what `_l10n_uy_ci_nie_is_valid()` already accepts (it strips `:. ,-` before checking the verification digit): ``` 3.402.010-1 or 34020101 (CI), 93.402.010-1 (NIE); dots and dash are optional ``` Only the `expected_format` string changes; the validation logic is untouched. Existing tests only assert the fixed part of the message (`The CI/NIE number.*does not seem to be valid`), so they are unaffected. Forward-Port-Of: odoo/odoo#282489
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.). **Observed behavior (date format):** * All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd
Original PR description
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale **Steps to reproduce:** * Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`) * Set the document…
* = de, din5008, din5008_purchase, din5008_repair, din5008_sale
**Steps to reproduce:**
* Install the **Germany - Accounting** (`l10n_de`) module (which pulls in `l10n_din5008`)
* Set the document layout to **DIN 5008** and generate any PDF report (invoice, quotation, purchase order, etc.).
**Observed behavior (date format):**
* All dates in the information block (Invoice Date, Due Date, Delivery Date, Order Date, etc.) are rendered in `yyyy-mm-dd` format instead of the expected `dd.MM.yyyy` format used in DE, AT, and CH.
**Observed behavior (commercial register):**
* The footer always shows `HRB-Nr.:` regardless of whether the company has a commercial register entry.
* The abbreviation `HRB-Nr.:` appears even for Austrian and Swiss companies, where the commercial register number is a German-specific concept.
* In the company form view, the field is labeled generically as "Company ID" instead of "Commercial Register Number" for German companies.
**Cause (date format):**
* All `t-options="{'widget': 'date'}"` directives across the DIN 5008 template family rely on the active user's language locale for date formatting. If the user language is not `de_DE`, dates render in the locale's default format (e.g. `yyyy-mm-dd` for `en_US`).
**Cause (commercial register):**
* The footer renders `company.company_registry` unconditionally with no country guard and no label.
**Fix (date format):**
* Add `'format': 'dd.MM.yyyy'` explicitly to all `t-options` date widgets across all DIN 5008 report templates (`l10n_din5008`, `l10n_din5008_sale`, `l10n_din5008_purchase`, `l10n_din5008_sale_subscription`, `l10n_din5008_repair`, `l10n_din5008_account_followup`, `l10n_din5008_industry_fsm`).
* This is correct for all three countries using DIN 5008 (DE, AT, CH), which all follow the `dd.MM.yyyy` convention.
**Fix (commercial register):**
* Remove the hardcoded `HRB-Nr.:` label from the footer and instead render `company.partner_id.company_registry_label` (which is country-aware).
* Update the duplicate contact warning message to use the country-aware label via `company.partner_id.company_registry_label`, backed by a new `_get_company_registry_labels` override in l10n_de that registers `Commercial Register Number` for `DE`.
* In the company form view (`l10n_de`), hide the generic "Company ID" field for German companies and show a relabeled instance with `string="Commercial Register Number"` instead.
opw-6392649
Forward-Port-Of: odoo/odoo#2790854 changes
Resolved issues and error corrections
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two mem
Original PR description
Before this commit, clicking a composer suggestion could leave the composer with the typed search instead of the selected name, as in the test "Mention a partner with special character (e.g. apostrophe ')" on runbot: Failed to find 1 of ".o-mail-Composer-input" with value "..." (Timeout of 10 seconds). Found 0 instead. This happens because NavigableList looks up the clicked option by index in its current props, while the item clicked comes from the last render. Typing "@" lists the two members of the channel and typing "Pyn" drops one of them: owl assigns the filtered options one frame before it patches the list, so a click in between looks up index 1 in a list of one option, finds nothing and returns. This commit passes the rendered option to the click handler, keeping the index lookup as a fallback so that the signature stays the same on a stable version. https://runbot.odoo.com/odoo/error/946154
It was possible to remove the image inside a card cover while keeping the figure wrapper. The card option would then still consider that there was a cover image even though the image was gone, which could also lead to a traceback. Steps to reproduce: - Insert the `s_three_columns` snippet - Click on the image of one card - Either press "Enter", "Delete", "Backspace" - Hover the "Cover Image" options => The image is removed but the `<figure>` is still there, so the option is still consid
Original PR description
It was possible to remove the image inside a card cover while keeping the figure wrapper. The card option would then still consider that there was a cover image even though the image was gone, which could also lead to a traceback. Steps to reproduce: - Insert the `s_three_columns` snippet - Click on the image of one card - Either press "Enter", "Delete", "Backspace" - Hover the "Cover Image" options => The image is removed but the `<figure>` is still there, so the option is still considered active (leading to a traceback) task-6081728
**Steps to reproduce:** * Set up a French company and configure Peppol E-invoicing. * Install `account_edi_ubl_cii` module. * Create a company partner (customer) and set a **Reference** value on the company contact under **Customer** -> **Settings** -> **Sales and Purchase**. * Create a child contact under that company and set a different Reference value. * Create an invoice using the child contact as the invoice partner and confirm the invoice. * Send it via Peppol.
Original PR description
**Steps to reproduce:**
* Set up a French company and configure Peppol E-invoicing.
* Install `account_edi_ubl_cii` module.
* Create a company partner (customer) and set a **Reference** value on the company contact under
**Customer** -> **Settings** -> **Sales and Purchase**.
* Create a child contact under that company and set a different Reference value.
* Create an invoice using the child contact as the invoice partner and confirm the invoice.
* Send it via Peppol.
**Observed Behaviour:**
* The BuyerReference in the generated XML contains the reference of the parent
(commercial partner) Instead of the child contact used on the invoice.
**Cause:**
* The buyer reference was taken from the commercial partner instead of the
invoice partner.
**Fix:**
* Update the condition to use the invoice partner's reference when available;
Otherwise, fall back on the commercial partner's reference.
opw - 6330649Currently, an error occurs when user tries to pay on a vendor bill and removes the currency. Steps to replicate: - Install `l10n_account_withholding_tax`and activate multiple currencies. - Open Invoicing > Vendors > Bills and create a new bill and add a vendor and bill date. - Add a product and tax `2% WTH`. - From the Cog menu > Click Pay > Remove the Currency. Error: ``` File '/home/odoo/src/odoo/saas-19.4/addons/l10n_account_withholding_tax/models/account_withholding_line.py', l
Original PR description
Currently, an error occurs when user tries to pay on a vendor bill and removes the currency. Steps to replicate: - Install `l10n_account_withholding_tax`and activate multiple currencies. - Open…
Currently, an error occurs when user tries to pay on a vendor bill and removes the currency.
Steps to replicate:
- Install `l10n_account_withholding_tax`and activate multiple currencies.
- Open Invoicing > Vendors > Bills and create a new bill and add a vendor and bill date.
- Add a product and tax `2% WTH`.
- From the Cog menu > Click Pay > Remove the Currency.
Error:
```
File '/home/odoo/src/odoo/saas-19.4/addons/l10n_account_withholding_tax/models/account_withholding_line.py', line 208, in _compute_original_amounts
line.original_base_amount = line_curr.round(base_amount * rate)
File '/home/odoo/src/odoo/saas-19.4/odoo/addons/base/models/res_currency.py', line 264, in round
self.ensure_one()
File '/home/odoo/src/odoo/saas-19.4/odoo/orm/models.py', line 5342, in ensure_one
raise ValueError('Expected singleton: %s' % self)
ValueError: Expected singleton: res.currency()
```
Cause:
- As the user removed currency, the `comodel_currency_id`is received as false.
- Later when we call `round()` on the empty res.currency recordset causes this error to occur.
Solution:
- Added the company currency as a fallback value when `currency_id` is removed by user, since `currency_id` is a required field user will need to select a currency when saving.
sentry-7616890592
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr2 changes
Documentation and clarification updates
Description of the issue/feature this PR addresses: Signed the Odoo Individual Contributor License Agreement to contribute to the Odoo repository. Current behaviour before PR: The CLA signature is missing for GitHub user `kshitij-nariya`, which will prevent future contributions from being accepted and merged. Desired behaviour after PR is merged: The CLA signature for `kshitij-nariya` is recorded in the repository, allowing future pull requests and contributions to be successfully merge
Original PR description
Description of the issue/feature this PR addresses: Signed the Odoo Individual Contributor License Agreement to contribute to the Odoo repository. Current behaviour before PR: The CLA signature is missing for GitHub user `kshitij-nariya`, which will prevent future contributions from being accepted and merged. Desired behaviour after PR is merged: The CLA signature for `kshitij-nariya` is recorded in the repository, allowing future pull requests and contributions to be successfully merged. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
**Problem:** Searching on free_qty can be slow when there are many stock.move and stock.quant. The search method uses _compute_quantities_dict() to compute the free_qty based on stock.move and stock.quant, which is expensive. **Solution:** A similar field, qty_available, has a faster search method based on stock.quant only. This method can be adapted to support fast searching on free_qty by also aggregating the reserved_qty and subtracting it from the qty_available. **Perf Table:** Reco
Original PR description
**Problem:** Searching on free_qty can be slow when there are many stock.move and stock.quant. The search method uses _compute_quantities_dict() to compute the free_qty based on stock.move and stock.quant, which is expensive. **Solution:** A similar field, qty_available, has a faster search method based on stock.quant only. This method can be adapted to support fast searching on free_qty by also aggregating the reserved_qty and subtracting it from the qty_available. **Perf Table:** Record: product.template, with ~20k stock.picking and most products w/o moves. |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |10k |2.14s |214 |370ms |45 | |50k |6.06s |644 |829ms |50 | |100k |11.42s |1196 |1.05s |46 | opw-6266096