Daily updates from Odoo
Wednesday, July 22, 2026
242 changes
7 changes
Resolved issues and error corrections
In this commit [1], the default-9 palette have been modified to dark for a POC, and has not been reverted to it's original color. This PR revert to the original colors. [1]: a26f2cef490408eb7c73623317f1b42050aa0f41 task-6325919
Original PR description
In this commit [1], the default-9 palette have been modified to dark for a POC, and has not been reverted to it's original color. This PR revert to the original colors. [1]: a26f2cef490408eb7c73623317f1b42050aa0f41 task-6325919
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic, 2 values C and D for it - C should have an extra price of 100 and 150 for D - Make a product with both of those product, set the price to 100 2 possibilities: - In the PoS, click the product, on the product popup, the price is 100 - This 100 is the product's price and does not change ev
Original PR description
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic,…
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic, 2 values C and D for it - C should have an extra price of 100 and 150 for D - Make a product with both of those product, set the price to 100 2 possibilities: - In the PoS, click the product, on the product popup, the price is 100 - This 100 is the product's price and does not change even if we change the values - Order that product and buy it with variants A and C - Click on the product again, the price is 300, which is correct - When we click on D, the price is reset to 100, but should be 350 **Why the fix:** When computing the popup's title, we try to get the current product based on the variants choices in the popup. If the product is found, we take that, because it means that it's already in the database. https://github.com/odoo/odoo/blob/0d7f5058664b501779b833609468e535b34356bf/addons/point_of_sale/static/src/app/components/popups/product_configurator_popup/product_configurator_popup.js#L260 If we do not find it, we just take the product template, which does not contain the current extra prices, which is why we got a price of 100 in the exemple. The product is not found because in the case of dynamic variants, the product is only created once it has been ordered at least once. Which means that for this newly created product, it is not yet in the database, so we take the product template instead of the product itself. We now also add the extra price for a product if it is undefined, meaning it has not been found in the database yet. We can't directly update the getter for the priceExtra, as it's also used to build the payload. As the rest of the code works fine with dynamic products with extra price the way it is sent now, we only change the title instead of changing the entire logic and computation. opw-6326125 Forward-Port-Of: odoo/odoo#273411
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/o
Original PR description
Before this commit: In some cases, an element may have a invisible `/n` first child from the html. When inserting content to it, the insert function doesn't check if the first child is visible, and then split the element wrongly. After this commit: we now check if the previous sibling of the current node is invisible, if so, we don't split the parent element. task-6352841 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277619 Forward-Port-Of: odoo/odoo#273958
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against the full table cell width, resulting in oversized content compared to other layouts. **Without fix:** <img width="1127" height="411" alt="withoutfix" src="https://github.com/user-attachments/assets/244c3407-1dbb-4b83-95d9-ebaba2b2b13c" /> For e.g, The folder layout wraps the same block in a `w-
Original PR description
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against…
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against the full table cell width, resulting in oversized content compared to other layouts. **Without fix:** <img width="1127" height="411" alt="withoutfix" src="https://github.com/user-attachments/assets/244c3407-1dbb-4b83-95d9-ebaba2b2b13c" /> For e.g, The folder layout wraps the same block in a `w-50` div, so percentage widths resolve against ~half the page width. <img width="1111" height="410" alt="folderexp" src="https://github.com/user-attachments/assets/ee72712a-94da-483c-9a8e-cb3a850dac8e" /> Added `w-50 ms-auto` to the `name="company_address"` div in the bubble layout to align its sizing context with the other layouts, ensuring consistent rendering of user-defined styles in `company_details` across both layouts. **With fix:** <img width="1119" height="413" alt="wfix" src="https://github.com/user-attachments/assets/6b1caf24-3a8e-450f-865e-cce2b9788fe9" /> Commit which made the bubble layout in table: https://github.com/odoo/odoo/commit/8eb61a245cd3b650e309fdb55d24654c34d785cd opw-6287230 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275421 Forward-Port-Of: odoo/odoo#270725
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
Original PR description
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
Miscellaneous changes
This reverts commit 787223c. In the point of sale, concurrent sales of the same product can happen, e.g. if several physical points of sales are open at the same time, each with their own session. In the case where the underlying product's valuation is tracked automatically and perpetually, the creation of the pos order leads to the creation of the stock picking, which in turn leads to a search for the next available svl. Because of the flush_all, this can cause lots of retry failures and ass
Original PR description
This reverts commit 787223c. In the point of sale, concurrent sales of the same product can happen, e.g. if several physical points of sales are open at the same time, each with their own session. In the case where the underlying product's valuation is tracked automatically and perpetually, the creation of the pos order leads to the creation of the stock picking, which in turn leads to a search for the next available svl. Because of the flush_all, this can cause lots of retry failures and associated delay/latency/overall perceived slowness for the end user. opw-6206709 Forward-Port-Of: odoo/odoo#276517 Forward-Port-Of: odoo/odoo#275264
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the forecast for all products/warehouses first and filters afterwards, so predicates like product_id can't reach the stock_move scan. This hurts single-product lookups such as _read_group() in mrp_report_bom_structure._get_stock_availability(), called repeatedly per component while rendering a BoM rep
Original PR description
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the…
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the forecast for all products/warehouses first and filters afterwards, so predicates like product_id can't reach the stock_move scan.
This hurts single-product lookups such as _read_group() in mrp_report_bom_structure._get_stock_availability(), called repeatedly per component while rendering a BoM report: each call does a full stock_move scan plus two sorts that spill to disk.
Marking all_sm NOT MATERIALIZED lets the planner inline it and push the product_id/warehouse_id filter down to an index scan, removing the full scan, the GENERATE_SERIES expansion and the on-disk sorts. warehouse_cte stays materialized (small and cheap).
Query generated from the _read_group:
```SQL
SELECT MIN("report_stock_quantity"."date")
FROM "report_stock_quantity"
WHERE (
(
(
(
("report_stock_quantity"."state" = 'forecast')
AND ("report_stock_quantity"."date" >= '2026-07-08')
)
AND ("report_stock_quantity"."product_id" = 15743)
)
AND ("report_stock_quantity"."product_qty" >= 1.0)
)
AND ("report_stock_quantity"."warehouse_id" = 4)
)
AND ("report_stock_quantity"."company_id" IN (1))
```
Before:
800 ms by _read_group in _get_stock_availability().
For opening a BoM overview with hundred of components takes 17 sec.
After:
25 ms by _read_group in _get_stock_availability().
Same BoM overview drops to 3 sec to open.
cc @Aurelienvd
I can send you EXPLAIN ANALYZE, but I prefer to not putting them here to avoid data leakage.
Forward-Port-Of: odoo/odoo#277235
Forward-Port-Of: odoo/odoo#2750225 changes
Resolved issues and error corrections
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against the full table cell width, resulting in oversized content compared to other layouts. **Without fix:** <img width="1127" height="411" alt="withoutfix" src="https://github.com/user-attachments/assets/244c3407-1dbb-4b83-95d9-ebaba2b2b13c" /> For e.g, The folder layout wraps the same block in a `w-
Original PR description
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against…
In the bubble layout, the `name="company_address"` div was inside an unconstrained `<td>`, causing percentage-based widths set in `company_details` (e.g. `width: 25%` on a image) to resolve against the full table cell width, resulting in oversized content compared to other layouts. **Without fix:** <img width="1127" height="411" alt="withoutfix" src="https://github.com/user-attachments/assets/244c3407-1dbb-4b83-95d9-ebaba2b2b13c" /> For e.g, The folder layout wraps the same block in a `w-50` div, so percentage widths resolve against ~half the page width. <img width="1111" height="410" alt="folderexp" src="https://github.com/user-attachments/assets/ee72712a-94da-483c-9a8e-cb3a850dac8e" /> Added `w-50 ms-auto` to the `name="company_address"` div in the bubble layout to align its sizing context with the other layouts, ensuring consistent rendering of user-defined styles in `company_details` across both layouts. **With fix:** <img width="1119" height="413" alt="wfix" src="https://github.com/user-attachments/assets/6b1caf24-3a8e-450f-865e-cce2b9788fe9" /> Commit which made the bubble layout in table: https://github.com/odoo/odoo/commit/8eb61a245cd3b650e309fdb55d24654c34d785cd opw-6287230 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275228 Forward-Port-Of: odoo/odoo#270725
From versions 18.3 to 19.3, company_id and siret refer to the same field. This caused an issue when connecting to the PDP using siret or siren could overwrite company_id. task-6327304 Forward-Port-Of: odoo/odoo#276805 Forward-Port-Of: odoo/odoo#275276
Original PR description
From versions 18.3 to 19.3, company_id and siret refer to the same field. This caused an issue when connecting to the PDP using siret or siren could overwrite company_id. task-6327304 Forward-Port-Of: odoo/odoo#276805 Forward-Port-Of: odoo/odoo#275276
The field pack_lot_ids is not present in the pos.order.line model anymore, so we need to remove it from the test. runbot-941527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
The field pack_lot_ids is not present in the pos.order.line model anymore, so we need to remove it from the test. runbot-941527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynch
Original PR description
Steps: - Enable `pos_hr` and configure employees - Open the POS - Log in as an employee - Open the burger menu in the navbar Issue: - The "Create Product" menu is not visible immediately after the employee logs in. - It only appears after refreshing the POS. Cause: - The visibility of the menu is determined when `Navbar` component is mounted. - Since the `Navbar` is mounted only once when the POS UI loads, the value is not updated after employee login. Fix: - Replace the asynchronous permission check with a getter that evaluates product creation rights. - Cache the group access information in `posService` and let the hr override use the getter. Task-6361787 Related PR: https://github.com/odoo/enterprise/pull/123073 Forward-Port-Of: odoo/odoo#277675 Forward-Port-Of: odoo/odoo#274420
Miscellaneous changes
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the forecast for all products/warehouses first and filters afterwards, so predicates like product_id can't reach the stock_move scan. This hurts single-product lookups such as _read_group() in mrp_report_bom_structure._get_stock_availability(), called repeatedly per component while rendering a BoM rep
Original PR description
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the…
all_sm is referenced by two branches of the outer UNION, so PostgreSQL materializes it (a CTE used more than once is an optimization fence). Every query on report_stock_quantity therefore builds the forecast for all products/warehouses first and filters afterwards, so predicates like product_id can't reach the stock_move scan.
This hurts single-product lookups such as _read_group() in mrp_report_bom_structure._get_stock_availability(), called repeatedly per component while rendering a BoM report: each call does a full stock_move scan plus two sorts that spill to disk.
Marking all_sm NOT MATERIALIZED lets the planner inline it and push the product_id/warehouse_id filter down to an index scan, removing the full scan, the GENERATE_SERIES expansion and the on-disk sorts. warehouse_cte stays materialized (small and cheap).
Query generated from the _read_group:
```SQL
SELECT MIN("report_stock_quantity"."date")
FROM "report_stock_quantity"
WHERE (
(
(
(
("report_stock_quantity"."state" = 'forecast')
AND ("report_stock_quantity"."date" >= '2026-07-08')
)
AND ("report_stock_quantity"."product_id" = 15743)
)
AND ("report_stock_quantity"."product_qty" >= 1.0)
)
AND ("report_stock_quantity"."warehouse_id" = 4)
)
AND ("report_stock_quantity"."company_id" IN (1))
```
Before:
800 ms by _read_group in _get_stock_availability().
For opening a BoM overview with hundred of components takes 17 sec.
After:
25 ms by _read_group in _get_stock_availability().
Same BoM overview drops to 3 sec to open.
cc @Aurelienvd
I can send you EXPLAIN ANALYZE, but I prefer to not putting them here to avoid data leakage.
Forward-Port-Of: odoo/odoo#277235
Forward-Port-Of: odoo/odoo#2750221 change
Resolved issues and error corrections
Currently, we only load the XML data from the exported POS order in the field `l10n_jo_edi_pos_computed_xml` when`l10n_jo_edi_pos_error` is False. It should be the opposite. The field `l10n_jo_edi_pos_computed_xml` is only used when we call `download_l10n_jo_edi_pos_computed_xml()` from the anchor "Download XML" , and that anchor is only visible when `l10n_jo_edi_pos_error` is True. If the request succeeds, then the XML file will be stored in the field `l10n_jo_edi_pos_xml_attachment_i
Original PR description
Currently, we only load the XML data from the exported POS order in the field `l10n_jo_edi_pos_computed_xml` when`l10n_jo_edi_pos_error` is False. It should be the opposite. The field `l10n_jo_edi_pos_computed_xml` is only used when we call `download_l10n_jo_edi_pos_computed_xml()` from the anchor "Download XML" , and that anchor is only visible when `l10n_jo_edi_pos_error` is True. If the request succeeds, then the XML file will be stored in the field `l10n_jo_edi_pos_xml_attachment_id` anyway. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276918
16 changes
Enhancements to existing features
Since [website builder refactor], a date field or a datetime that appears in the page is not editable from website builder. This commit re-introduces the ability to do so. [website builder refactor]: 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-6230582 Forward-Port-Of: odoo/odoo#270325
Original PR description
Since [website builder refactor], a date field or a datetime that appears in the page is not editable from website builder. This commit re-introduces the ability to do so. [website builder refactor]: 9fe45e2b7ddbbfd0445ffe25a859e67a316d02b2 task-6230582 Forward-Port-Of: odoo/odoo#270325
Resolved issues and error corrections
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#276356 Forward-Port-Of: odoo/odoo#273905
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276356 Forward-Port-Of: odoo/odoo#273905
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing t
Original PR description
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ###…
### Steps to reproduce 1. Trigger an error whose browser object has no `stack` property (for example, a `DOMException` such as `AbortError`). 2. Let the web error service format its traceback. ### Current behavior `formatTraceback()` calls `error.stack.split(...)` unconditionally, which raises a second `TypeError` and masks the original error. ### Expected behavior The original error is formatted and reported even when the browser does not provide a stack trace. ### Fix Use the existing technical name and message as the traceback when `stack` is absent. A focused regression test covers an `AbortError`-like object without `stack`. ### Tests - `git diff --check` - `node --check addons/web/static/src/core/errors/error_utils.js` - `node --check addons/web/static/tests/core/errors/error_service.test.js` - `@web/core/errors` HOOT suite: 24 tests, 107 assertions passed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr. Forward-Port-Of: odoo/odoo#276864
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
Original PR description
Invoice dashboard data, specifically DSO, was incorrectly aligned due to a mismatch in the fiscal year structure. Task-6049887 Forward-Port-Of: odoo/odoo#275880 Forward-Port-Of: odoo/odoo#261037
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References:
Original PR description
### Description: When importing a Peppol invoice containing a massive embedded attachment, the `lxml` library throws an `lxml.etree.XMLSyntaxError: huge text node` error. This is a built-in safety check in libxml2 designed to prevent DoS attacks via XML entity expansion or malicious bombs [^1]. Rather than disabling this security protection globally using the `huge_tree` parser flag, we pre-process and trim the raw XML to remove the heavy binary nodes before parsing. ### References: opw-6085893 [^1]: https://lxml.de/6.0/FAQ.html#is-lxml-vulnerable-to-xml-bombs Forward-Port-Of: odoo/odoo#275893 Forward-Port-Of: odoo/odoo#275367
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure t
Original PR description
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027.…
### Issue before this commit: Sending a TicketBAI invoice to a customer with a Spanish address and a VAT number starting with 'N' (Non-resident entity) resulted in a rejection with error B4_2000027. The XML incorrectly generated the national <DesgloseFactura> tag instead of the required <DesgloseTipoOperacion> tag. ### Steps to reproduce the issue: 1. Download Accounting, l10n_es and l10n_es_edi_tbai 2. Change name to ES Company into “NOMBRE APELLIDOUNO APELLIDODOS” (this is to make sure the certificate for Ticketbai works) 3. Go to Settings → Spain Localization → set Tax Agency for = Bizkaia 4. Change VAT number for customer Mulhacén Digital S.L. into N0011452J (must be a foreign entity ID) 5. Go to Settings > Technical > System Parameters and set the parameter 'l10n_es_edi_tbai.epigrafe' to 165360 6. Create a new invoice for that client and try to send it to TicketBAI 7. Error: B4_1000002: Todos los registros incluidos en la petición son incorrectos. B4_2000027: La factura contiene un Tipo de desglose incorrecto. Ha de ser a nivel de operación cuando la factura es completa y, además, existe destinatario extranjero (tipo IDOtro o que sea NIF que empiece por N) o la Clave de IVA es 02. ### Cause of the issue: The _l10n_es_is_foreign() method evaluated these customers as domestic because their country was set to Spain and their VAT did not start with "ESN". It failed to recognize a standalone "N" prefix as a valid foreign identifier. https://github.com/odoo/odoo/blob/75ae45861e2f417aa2b90bdb2b2869718e091c09/addons/l10n_es/models/res_partner.py#L7-L10 ### Reason to introduce the fix: Adding the 'N' prefix to the _l10n_es_is_foreign() check ensures the system correctly treats these entities as foreign for tax purposes. This generates the correct XML structure automatically, without forcing users to unnaturally prepend "ES" to a legally valid NIF. opw-6326359 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275231
Before this commit, a many2one field test could sometimes fail because of an unexpected web_name_search in verifySteps. That extra call followed the `.clear()` of the input, which triggers a debounced search. Depending on the timing, that call sometimes occured before the end of the test (and the destroy of the component). Now, it is always performed. runbot error~944206 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merge
Original PR description
Before this commit, a many2one field test could sometimes fail because of an unexpected web_name_search in verifySteps. That extra call followed the `.clear()` of the input, which triggers a debounced search. Depending on the timing, that call sometimes occured before the end of the test (and the destroy of the component). Now, it is always performed. runbot error~944206 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#276962 Forward-Port-Of: odoo/odoo#276799
In restaurant mode, a direct sale order (no table, no floating order name) has no display name yet when it is sent to the preparation printer. `getName()` returns "Direct sale" in that case, which appeared as the order name on the preparation ticket. Add a `preparationName` getter on `PosOrder` that, for direct sale orders, falls back to `floatingOrderName || pos_reference` so the ticket always shows a meaningful reference. For non-direct-sale orders the getter delegates to `getName()` unchan
Original PR description
In restaurant mode, a direct sale order (no table, no floating order name) has no display name yet when it is sent to the preparation printer. `getName()` returns "Direct sale" in that case, which appeared as the order name on the preparation ticket. Add a `preparationName` getter on `PosOrder` that, for direct sale orders, falls back to `floatingOrderName || pos_reference` so the ticket always shows a meaningful reference. For non-direct-sale orders the getter delegates to `getName()` unchanged. Task-6327397 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#271743
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2
Original PR description
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are…
Before this commit, the maximum weight and volume allowed on a delivery method were checked against transfers using the quantity in the unit of the move, while the weight and volume of a product are expressed per reference unit. The same checks on sale orders already use the quantity in the reference unit. Steps to reproduce: - create a delivery method with a maximum weight of 10 kg - create a product in Units weighing 1 kg with Dozens in its allowed units - create a delivery transfer of 2 Dozen of the product and select the carrier on the transfer The 24 kg shipment is weighed as 2 kg, so the carrier is proposed on the transfer although it exceeds its maximum weight, and it is correctly refused on a sale order for the same quantity. With a unit smaller than the reference one, valid carriers are hidden instead. Solution: Use the quantity in the reference unit of the product, as done for sale orders and everywhere else the shipment weight is computed. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277425
When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354 Forward-Port-Of: odoo/odoo#272472
Original PR description
When an attachment is added to an email template and is linked to a journal, and then you try to send an invoice, the attachment is shown in the attachments box but is not sent via peppol, the reason is that we were filtering to send only manually added attachments, and the email attachment was not considered "manual". task-id-6241354 Forward-Port-Of: odoo/odoo#272472
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic, 2 values C and D for it - C should have an extra price of 100 and 150 for D - Make a product with both of those product, set the price to 100 2 possibilities: - In the PoS, click the product, on the product popup, the price is 100 - This 100 is the product's price and does not change ev
Original PR description
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic,…
**Steps to reproduce:** - Create an attribute of type always, 2 values A and B for it - The two values should have an extra price, like 100 for A and 150 for B - Create an attribute of type dynamic, 2 values C and D for it - C should have an extra price of 100 and 150 for D - Make a product with both of those product, set the price to 100 2 possibilities: - In the PoS, click the product, on the product popup, the price is 100 - This 100 is the product's price and does not change even if we change the values - Order that product and buy it with variants A and C - Click on the product again, the price is 300, which is correct - When we click on D, the price is reset to 100, but should be 350 **Why the fix:** When computing the popup's title, we try to get the current product based on the variants choices in the popup. If the product is found, we take that, because it means that it's already in the database. https://github.com/odoo/odoo/blob/0d7f5058664b501779b833609468e535b34356bf/addons/point_of_sale/static/src/app/components/popups/product_configurator_popup/product_configurator_popup.js#L260 If we do not find it, we just take the product template, which does not contain the current extra prices, which is why we got a price of 100 in the exemple. The product is not found because in the case of dynamic variants, the product is only created once it has been ordered at least once. Which means that for this newly created product, it is not yet in the database, so we take the product template instead of the product itself. We now also add the extra price for a product if it is undefined, meaning it has not been found in the database yet. We can't directly update the getter for the priceExtra, as it's also used to build the payload. As the rest of the code works fine with dynamic products with extra price the way it is sent now, we only change the title instead of changing the entire logic and computation. opw-6326125 Forward-Port-Of: odoo/odoo#273411
Before this PR, the tour could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js` file, allowing the next tour step to run before the loader was shown. After this PR, the tour waits for `o_loading_screen`, which is added immediately and remains until the operation finishes. This ensures the tour waits correctly before proceeding. runbot-[941508](https://runbot.odoo.com/odoo/error/941508)
Original PR description
Before this PR, the tour could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js` file, allowing the next tour step to run before the loader was shown. After this PR, the tour waits for `o_loading_screen`, which is added immediately and remains until the operation finishes. This ensures the tour waits correctly before proceeding. runbot-[941508](https://runbot.odoo.com/odoo/error/941508)
**Description of the issue/feature this PR addresses:** ---------------------------------------------- On mobile devices, the meeting view had two UI issues affecting the call experience. The call permission dialog could display an unwanted focus outline around its content because the dialog body was focused on touch devices. Additionally, meeting action buttons could be partially hidden, especially in portrait mode, as the meeting view could extend beyond the visible viewport height.
Original PR description
**Description of the issue/feature this PR addresses:** ---------------------------------------------- On mobile devices, the meeting view had two UI issues affecting the call experience. The call…
**Description of the issue/feature this PR addresses:** ---------------------------------------------- On mobile devices, the meeting view had two UI issues affecting the call experience. The call permission dialog could display an unwanted focus outline around its content because the dialog body was focused on touch devices. Additionally, meeting action buttons could be partially hidden, especially in portrait mode, as the meeting view could extend beyond the visible viewport height. **Current behavior before PR:** ---------------------------------------------- - Opening the call permission dialog on mobile could show an unwanted focus outline around the dialog content - Meeting action buttons could be partially hidden on mobile devices - In portrait mode, the footer could overflow below the visible viewport **Desired behavior after PR is merged:** ---------------------------------------------- - Call permission dialog opens on mobile without showing the unwanted focus outline on main body. - Meeting action buttons remain fully visible on mobile devices Task-6232825 ---------------------------------------------- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Issue: In "l10n standalone" for l10n_ke, .`test_cogs_kit_multi_steps_first_step_validated` failed. Steps to reproduce: - install `l10_ke_edi_oscu_stock` and `sale_mrp` - run `test_cogs_kit_multi_steps_first_step_validated` Cause: `l10_ke_edi_oscu_stock` override the compute for product `invoice_policy`. Product from Kenyan company or withour company are by default set to invoice on delivery. Therefore, setting a two steps delivery require to validate picking then shipping bef
Original PR description
Issue:
In "l10n standalone" for l10n_ke, .`test_cogs_kit_multi_steps_first_step_validated` failed.
Steps to reproduce:
- install `l10_ke_edi_oscu_stock` and `sale_mrp`
- run `test_cogs_kit_multi_steps_first_step_validated`
Cause:
`l10_ke_edi_oscu_stock` override the compute for product `invoice_policy`. Product from
Kenyan company or withour company are by default set to invoice on delivery. Therefore,
setting a two steps delivery require to validate picking then shipping before invoicing.
As products are not required to be invoiced on delivery by any l10n, it is possible to force
test products to have invoice_policy set to 'order' and not to depend on l10n default value.
runbot-940390Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal access rights (only access rights to their own sales orders and invoices). 2. Sign in as that user and create a sales order and confirm it. 3. Create an invoice for that sales order and validate it. 4. Sign in as an administrator and create a duplicate sales order for that sales order, but as
Original PR description
Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal…
Problem: Some users with limited access rights cannot access invoices they created, after another user duplicates their sales order and invoices it. Steps to reproduce: 1. Create a user with minimal access rights (only access rights to their own sales orders and invoices). 2. Sign in as that user and create a sales order and confirm it. 3. Create an invoice for that sales order and validate it. 4. Sign in as an administrator and create a duplicate sales order for that sales order, but assign it to a different user (not the one created in step 1). 5. Confirm the duplicate sales order, create an invoice for it and validate it. 6. Sign in as the user created in step 1 and try to access the invoice created in step 3. 7. Note the access error Cause: When reading an account.move record, the system searches for duplicate moves and adds them to the duplicated_ref_ids field. However, it does not check if the user has read access to those duplicate moves, which leads to access errors when trying to access the main account.move record (which the user has read access to) because the system tries to read the duplicate moves (which the user does not have read access to). opw-6374566 Forward-Port-Of: odoo/odoo#276547
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
Original PR description
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
6 changes
Resolved issues and error corrections
Problem: When a table (or banner, or columns block) is placed inside a toggle block, deleting the last paragraph in a table cell creates a new block after the toggle block and moves the selection outside the table. Cause: `handleDeleteBackwardContentEnd` assumes the deleted block is always a direct child of the toggle content. However, the deleted block may be nested inside a table, banner, or columns block. Solution: Only create a new block after the toggle block when the selected bloc
Original PR description
Problem: When a table (or banner, or columns block) is placed inside a toggle block, deleting the last paragraph in a table cell creates a new block after the toggle block and moves the selection outside the table. Cause: `handleDeleteBackwardContentEnd` assumes the deleted block is always a direct child of the toggle content. However, the deleted block may be nested inside a table, banner, or columns block. Solution: Only create a new block after the toggle block when the selected block is a direct child of the toggle content. Steps to reproduce: - Add a toggle block. - Insert a table inside its content. - Add two paragraphs to a table cell. - Delete the last paragraph. - Observe that a new block is created after the toggle block and the selection moves outside the table. opw-6382058 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
There is a warning saying that there is no "true" field when editing the view. But in reality this is currently working as expected and the field is hidden. opw-6398588
Original PR description
There is a warning saying that there is no "true" field when editing the view. But in reality this is currently working as expected and the field is hidden. opw-6398588
Note: In odoo all date/datetime fields are stored and computed by default as UTC Before this commit, dates were called using local timezone getters. This caused the time returned from web to be shifted by the timezone as the dates returned would be treated as UTC. After this commit, dates are now called using UTC timzone getters. Now all web times are retrived as UTC and in sync with the rest of the odoo fields and computations. task-6271421 Forward-Port-Of: odoo/odoo#276683 Forward-Po
Original PR description
Note: In odoo all date/datetime fields are stored and computed by default as UTC Before this commit, dates were called using local timezone getters. This caused the time returned from web to be shifted by the timezone as the dates returned would be treated as UTC. After this commit, dates are now called using UTC timzone getters. Now all web times are retrived as UTC and in sync with the rest of the odoo fields and computations. task-6271421 Forward-Port-Of: odoo/odoo#276683 Forward-Port-Of: odoo/odoo#265250
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment
Original PR description
Before this commit, the journal and the memo of a payment linked to a company-paid expense report could be modified although such payments must be kept consistent with their expense report: a missing comma in the set of protected fields merged 'journal_id' and 'ref' into a single meaningless entry. The memo was also left editable because the set still referred to 'ref', which was renamed to 'memo'. Steps to reproduce: - submit, approve and post an expense paid by company - open the payment created for the expense report - edit the memo or the journal and save, then try to edit the date Editing the date is refused with "You cannot do this modification since the payment is linked to an expense report", while the memo and journal changes are silently accepted. Solution: Restore the missing comma and protect the renamed memo field. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277423
Reverse charge taxes (Inversione Contabile) should have the translated code ending with 'IC' (the acronym), not 'CI'. Suggested by partner: eLBati task-none Forward-Port-Of: odoo/odoo#277465 Forward-Port-Of: odoo/odoo#276270
Original PR description
Reverse charge taxes (Inversione Contabile) should have the translated code ending with 'IC' (the acronym), not 'CI'. Suggested by partner: eLBati task-none Forward-Port-Of: odoo/odoo#277465 Forward-Port-Of: odoo/odoo#276270
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
Original PR description
The context variable skip_is_manually_modified needs to be passed in order for the autoposting feature to work. The is_manually_modified variable of the move needs to evaluate to true Fixes error in test TestInvoiceExtract.test_autopost_bills_ocr for mc and fr localizations Related pr: https://github.com/odoo/odoo/pull/271865 runbot-6369932 Forward-Port-Of: odoo/odoo#276953
5 changes
Resolved issues and error corrections
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of consumable component") AssertionError: 3.07 != 1.53 within 7 places (1.5399999999999998 difference) : Should not include the value of consumable component ``` The test delivered 1 whole unit of every component of Kit A regardless of the fractional quantity actually needed to produce a single kit
Original PR description
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of…
Steps to reproduce the bug: - Install l10n_ke_edi_oscu_stock - Run Test_sale_mrp_kit_bom_cogs Problem: ```self.assertAlmostEqual(stock_out_aml.credit, 1.53, msg="Should not include the value of consumable component") AssertionError: 3.07 != 1.53 within 7 places (1.5399999999999998 difference) : Should not include the value of consumable component ``` The test delivered 1 whole unit of every component of Kit A regardless of the fractional quantity actually needed to produce a single kit (0.34/0.14/0.2 units for Component A/B/BB respectively). This went unnoticed under the default invoice_policy 'order', since qty_delivered never drives the invoiced quantity in that case. l10n_ke_edi_oscu_stock forces invoice_policy to 'delivery' for storable products that have no explicit company_id, which is the case for the products created in this test. With invoice_policy 'delivery', _compute_kit_quantities() correctly reads the over-delivered components as enough stock to form 2 complete kits (min ratio 2.94, floored to 2) instead of 1, doubling the invoiced quantity and the resulting COGS (3.07 instead of 1.53). runbot-243633
Firefox has a strict limit of ~640,000 characters for history state serialization and throws NS_ERROR_ILLEGAL_VALUE past it. Chrome and Safari throw DataCloneError past their own undocumented limits (~500MB and ~64MB respectively). When a debounced push() exceeded these limits, the error was unhandled and broke navigation. Catch these two specific errors and log them instead of crashing, while still resetting the push state and re-throwing any other unexpected error. opw-6182687
Original PR description
Firefox has a strict limit of ~640,000 characters for history state serialization and throws NS_ERROR_ILLEGAL_VALUE past it. Chrome and Safari throw DataCloneError past their own undocumented limits (~500MB and ~64MB respectively). When a debounced push() exceeded these limits, the error was unhandled and broke navigation. Catch these two specific errors and log them instead of crashing, while still resetting the push state and re-throwing any other unexpected error. opw-6182687
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document, the context incorrectly retains the `active_id` and `active_model` of the alias. This causes subsequent smart button actions on the parent document to evaluate
Original PR description
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe…
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document, the context incorrectly retains the `active_id` and `active_model` of the alias. This causes subsequent smart button actions on the parent document to evaluate using the wrong ID. **Solution:** Update the context dictionary returned by the `action_open_parent_document` method. We set `active_id` and `active_model` to match the parent document in order to ensure that the web client drops the outdated alias data. ### Current behavior before PR: Clicking a smart button (ex. "Tickets") on the parent document evaluates the action using the old alias ID. Because that ID does not actually belong to the target model, the database search fails and causes a MissingError. ### Desired behavior after PR: The context will accurately update with the parent document's ID and model upon navigation. All subsequent smart button actions should receive the correct ID, allowing the views to load normally without crashing. opw-6395638 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document, the context incorrectly retains the `active_id` and `active_model` of the alias. This causes subsequent smart button actions on the parent document to evaluate
Original PR description
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe…
### Steps to Reproduce: 1. In Debug mode, go to Aliases 2. Click on any active Alias, ex. customer-care 3. Click on "Open Parent Document" smart button 4. Click on "Tickets" smart button and observe error ### Description of the issue/feature this PR addresses: **Issue:** When navigating from an email alias to its parent document, the context incorrectly retains the `active_id` and `active_model` of the alias. This causes subsequent smart button actions on the parent document to evaluate using the wrong ID. **Solution:** Update the context dictionary returned by the `action_open_parent_document` method. We set `active_id` and `active_model` to match the parent document in order to ensure that the web client drops the outdated alias data. ### Current behavior before PR: Clicking a smart button (ex. "Tickets") on the parent document evaluates the action using the old alias ID. Because that ID does not actually belong to the target model, the database search fails and causes a MissingError. ### Desired behavior after PR: The context will accurately update with the parent document's ID and model upon navigation. All subsequent smart button actions should receive the correct ID, allowing the views to load normally without crashing. opw-6395638 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes
Original PR description
The character-by-character HTML assertion in mass mailing tests fails on modern platforms using libxml2 >= 2.14/2.15 due to upstream updates that align HTML serialization, attribute quote management, and escaping rules more closely with the HTML5 specification. See upstream changes: - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.0 (Attribute escaping optimization) - https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.15.0 (HTML5 spec compliant serialization) This commit fixes this by refactoring the assertions to treat the output HTML structure as a "black box", verifying data integrity and expected content conversions rather than brittle structural layout. runbot-938228 Forward-Port-Of: odoo/odoo#275959
2 changes
Resolved issues and error corrections
iOS devices currently display the first letter of the website name instead of a favicon when creating a shortcut. This commit adds the `apple-touch-icon` link tag referencing the favicon to ensure the icon displays correctly. This commit is a backport of [1], which was merged in master(saas-19.2). task-5427275 [1]: https://github.com/odoo/odoo/commit/2506fdfc49f1515aea7e715e9f6d66418a093401
Original PR description
iOS devices currently display the first letter of the website name instead of a favicon when creating a shortcut. This commit adds the `apple-touch-icon` link tag referencing the favicon to ensure the icon displays correctly. This commit is a backport of [1], which was merged in master(saas-19.2). task-5427275 [1]: https://github.com/odoo/odoo/commit/2506fdfc49f1515aea7e715e9f6d66418a093401
Before this commit, when adding a line without a product to an invoice or credit note, `_get_most_frequent_account_for_partner` picked the partner's most-used account, filtered to an income or expense account depending on `get_inbound_types` and `get_outbound_types`. Those helpers classify move types by cash-flow direction which is correct for choosing a receivable and payable account but wrong for choosing an income ro expense account: they group `in_refund` with `out_invoice` as "inbound",
Original PR description
Before this commit, when adding a line without a product to an invoice or credit note, `_get_most_frequent_account_for_partner` picked the partner's most-used account, filtered to an income or…
Before this commit, when adding a line without a product to an invoice or credit note, `_get_most_frequent_account_for_partner` picked the partner's most-used account, filtered to an income or expense account depending on `get_inbound_types` and `get_outbound_types`. Those helpers classify move types by cash-flow direction which is correct for choosing a receivable and payable account but wrong for choosing an income ro expense account: they group `in_refund` with `out_invoice` as "inbound", and `out_refund` with `in_invoice` as "outbound". As a result, a Vendor Credit Note line with no product would be filtered to income accounts instead of expense accounts, and a Customer Credit Note line to expense accounts instead of income accounts. This only surfaced for contacts who are both customer and vendor, since the query needs matching history to return a result; otherwise it silently falls back to the journal's default account, masking the bug for ordinary contacts. This commit uses `get_sale_types` and `get_purchase_types` instead, which classify by document side, sale vs. purchase rather than cash-flow direction, matching the classification already used for product-based lines `is_sale_document` and `is_purchase_document` opw-6373124 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr