Daily updates from Odoo
Tuesday, July 28, 2026
344 changes
8 changes
Enhancements to existing features
In some cases, you want to redirect a record with ModelConverter, whatever the slug value. E.g. /shop/old-name-1 => /shop/alt-product-10 /shop/new-name-1 => /shop/alt-product-10 /fr/shop/nom-1 => /shop/alternatif-product-10 /de/shop/produktname-1 => /de/shop/produktname-10 In this case, adding only one redirect /shop/1 => /shop/10 covers the need to support all the translated slugs and the old name that we remember. On odoo.com we have this need e.g. when we archive a
Original PR description
In some cases, you want to redirect a record with ModelConverter, whatever the slug value.
E.g. /shop/old-name-1 => /shop/alt-product-10
/shop/new-name-1 => /shop/alt-product-10
/fr/shop/nom-1 => /shop/alternatif-product-10
/de/shop/produktname-1 => /de/shop/produktname-10
In this case, adding only one redirect /shop/1 => /shop/10 covers the need to support all the translated slugs and the old name that we remember.
On odoo.com we have this need e.g. when we archive a Job Position, we create a redirect, but in some cases the job position is translated or has been renamed and we don't remember all the old urls. With this change, we will be able to redirect all old urls, translated urls, ... with only one redirect.
/jobs/10 -> /explore-more-opportunities-with-us
task-6391567
Forward-Port-Of: odoo/odoo#276515We now avoid sharing logs to the database in favor of logging using sentry. task-6329137
Original PR description
We now avoid sharing logs to the database in favor of logging using sentry. task-6329137
Resolved issues and error corrections
Before this commit, opening demo data CRM "Modern Open Space" and clicking on "Send message" of chatter would lead to a crash in debug mode. This happens because RecipientTags receive props `resId: false` that doesn't follow props validation that expects a number. This is a change from owl3 where the type of props was not validated but was restricted to `number`, although there were genuine cases of `false` value. This commit adds `false` as an expected value of `resId` props of `Recipi
Original PR description
Before this commit, opening demo data CRM "Modern Open Space" and clicking on "Send message" of chatter would lead to a crash in debug mode. This happens because RecipientTags receive props `resId: false` that doesn't follow props validation that expects a number. This is a change from owl3 where the type of props was not validated but was restricted to `number`, although there were genuine cases of `false` value. This commit adds `false` as an expected value of `resId` props of `RecipientTag`. Task-6424706
A `<video>` element with an active srcObject is exempt from normal DOM garbage collection by the browser, even once detached and dereferenced, so the component stays retained through its loadedmetadata listener [1]. This showed up as ComponentNode instances piling up in memory snapshots across the call hoot test suite. Clear srcObject (and reload) on unmount to let the element, and everything it retains, be garbage collected. [1] https://html.spec.whatwg.org/multipage/media.html#best-pract
Original PR description
A `<video>` element with an active srcObject is exempt from normal DOM garbage collection by the browser, even once detached and dereferenced, so the component stays retained through its loadedmetadata listener [1]. This showed up as ComponentNode instances piling up in memory snapshots across the call hoot test suite. Clear srcObject (and reload) on unmount to let the element, and everything it retains, be garbage collected. [1] https://html.spec.whatwg.org/multipage/media.html#best-practices-for-authors-using-media-elements 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
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303 Forward-Port-Of: odoo/odoo#278423
Original PR description
`Store._deep_freeze()` converted callables to their `__code__` object when building immutable cache keys. While code objects are hashable, keeping them directly in the frozen structure unnecessarily ties cache keys to runtime objects. Instead, identify functions by the hash of their code object. This keeps the ability to distinguish functions without holding a reference to the code object longer than necessary. task-6410303 Forward-Port-Of: odoo/odoo#278423
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo. That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on th
Original PR description
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are…
Commit: odoo/odoo@2406a96765cc76de94d356dfd3b27cf98de82d7 made the computation of related fields go through `sudo()` unconditionally, to keep cache consistency with x2m related fields, which are themselves fetched in sudo.
That override, however, applies to every many2one related/inherited field, not just x2m ones, and ignores the field's own `compute_sudo` attribute. For a field with `compute_sudo=False`, the compute is still forced through `sudo()`, while every subsequent cache lookup on that field (in `Field.__get__`) is done on the non-sudo environment.
This is visible on `res.users.main_user_id`, an inherited field `res.partner.main_user_id` (compute_sudo=False, depends_context('uid')). The compute succeeds, but the resulting value is written into the sudo cache instead of the caller's cache, so the non-sudo cache check right after considers it missing:
```py
File "/home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py", line 1827, in __get__
raise ValueError(f"Compute method failed to assign {missing_recs}.{self.name}")
ValueError: Compute method failed to assign res.users(2,).main_user_id
```
Confirmed in pdb: the id is missing from the plain cache but present in the sudo one:
```py
> /home/odoo/src/odoo/saas-19.3/odoo/orm/fields.py(1823)__get__()
-> missing_recs_ids = tuple(self._cache_missing_ids(recs))
(Pdb) tuple(self._cache_missing_ids(recs))
(2,)
(Pdb) tuple(self._cache_missing_ids(recs.sudo()))
()
```
Steps to reproduce:
- in saas~19.3, open the Users list view
- using Studio, add the `main_user_id` field to the list view
- the view fails to load with: "The requested change caused an error in the view. It could be because a field was deleted, but still used somewhere else."
- The error in logs is the `ValueError` mentioned above
Restrict the forced `sudo()` to x2m fields, which is what the original comment describes and what actually needs it, and let many2one related fields honor their own `compute_sudo` like every other compute does.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278651## Short fix summary: `res.partner.company_registry` was removed by a core refactor (6f8c2526a00d), which broke `l10n_ge`'s demo data install since `demo/demo_company.xml` still set that field. This drops the field, and adds two demo customer partners (individual + business TIN format) so there's actually someone to invoice in a demo/test flow. no-task-id I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
## Short fix summary: `res.partner.company_registry` was removed by a core refactor (6f8c2526a00d), which broke `l10n_ge`'s demo data install since `demo/demo_company.xml` still set that field. This drops the field, and adds two demo customer partners (individual + business TIN format) so there's actually someone to invoice in a demo/test flow. no-task-id I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
3 changes
Resolved issues and error corrections
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rat
Original PR description
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes…
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rather than the savable selectors resource. As a result, elements which had the `o_not_editable` class, such as job location, did not have `o_savable` added to them. These elements were excluded from the builder's dirty-tracking for save. Therefore, editing the location didn't mark the element as changed and saving to drop the update. Fix: Remove `o_not_editable` from the location element on plugin setup so the field is now editable and savable through the builder option. This surfaced a second issue: when the location was set to "Remote", the element's content could be directly editable inline. Saving it that way disconnected the content from the job location field. This was fixed by adjusting the selector that determines when a many2one's content is editable inline. The result is the "Remote" case is handled consistently as changing to any other location. [1]: https://github.com/odoo/odoo/commit/f3c119dd034b4c3df9f392b0cdc66a1141662c25 Task-6311200 Forward-Port-Of: odoo/odoo#274731
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max
Original PR description
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt…
Steps to reproduce ------------------ 1. install l10n_sa_edi and l10n_sa_pos 2. onboard the company for ZATCA and link a printer to the PoS 3. make a PoS order with a customer and print the receipt -> the ZATCA QR code is too small to be scanned. Why it's happening ------------------ The phase 2 QR code is big because it also contains the invoice hash, signature and public key. We render it at 200 px, which is too small to scan a QR with that much data. The QR image also has no max width, so it gets cut when the receipt is narrow. The fix ------- Render it at 400 px, and add `max-width: 100%` so it is not cut on a narrow receipt. opw-6399766 Before <img width="647" height="1036" alt="image" src="https://github.com/user-attachments/assets/6bcb8526-71a8-4d9f-8372-219959416214" /> After <img width="649" height="1031" alt="image" src="https://github.com/user-attachments/assets/70f5fdb5-ba71-4fbe-8f03-ef0a1b29be2e" /> Forward-Port-Of: odoo/odoo#278499 Forward-Port-Of: odoo/odoo#277813
14 changes
Enhancements to existing features
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Chan
Original PR description
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Change Password URL specification by exposing a public route that redirects to `/web/reset_password`. Reference: https://wicg.github.io/change-password-url/ --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277575
Resolved issues and error corrections
Helpers for the enterprise PR opw-5862529 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#278518 Forward-Port-Of: odoo/odoo#270624
Original PR description
Helpers for the enterprise PR opw-5862529 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#278518 Forward-Port-Of: odoo/odoo#270624
### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longe
Original PR description
### Issue: In the tax report, lines linked to the T section show 0 and a danger warning is displayed after posting an invoice with a tax using a `T_base` tax grid ### Cause: In 19.0, the +/- tax grids were replaced by a single unsigned tax grid The T formulas were not updated accordingly, causing their values to be negative instead of positive `_customize_warnings` compares the sum of `08+09+9B+10+11+T1->T7` against `A1+A2+A3+B2+B3+B4` With incorrect signs on T lines, the sums no longer match and a danger warning is displayed above the report ### Steps to reproduce: - Install `l10n_fr_account` - Create a Tax (Amount: 1.75%, Base Tax Grids: A1 and T1_base, 100 of tax: T1_taxe) - Create an invoice (any amount, Tax: created tax) - Open the Tax Report for this month Before the fix, a red warning is raised: Sum of 08+09+9B+10+11+T1->T7 is not equal to sum of A1+A2+A3+B2+B3+B4 opw-6357703 Forward-Port-Of: odoo/odoo#276446
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 Forward-Port-Of: odoo/odoo#277519
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a
Original PR description
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which…
Description of the issue/feature this PR addresses: A cash rounding line resolves its company-dependent profit/loss account against the active company instead of the invoice's own company, which breaks multi-company invoicing whenever the invoice's company differs from the active one. Current behavior before PR: - Enable Multi-Companies in the settings. - Create a second company (Company B). - Open Accounting > Configuration > Cash Roundings. - Create a cash rounding with strategy "Add a rounding line" and precision 1.00. - Make Company A the active company in the company switcher. - Set the cash rounding's profit and loss accounts to Company A accounts. - Switch the active company to Company B. - Set the cash rounding's profit and loss accounts to Company B accounts. - Make Company A the active company again, keeping both companies active. - Create a customer invoice for Company B. - Add one invoice line whose total is not a multiple of the rounding precision. - Set the invoice's cash rounding to the one above. > Adding the rounding line raises a cross-company UserError: the company-dependent account is resolved against Company A while the invoice belongs to Company B. Desired behavior after PR is merged: The rounding line resolves the company-dependent profit/loss account against the invoice's own company, so the rounding line always uses that company's account and no cross-company error is raised. Covered by the added test TestAccountMoveCashRoundingMultiCompany. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278401 Forward-Port-Of: odoo/odoo#273410
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rat
Original PR description
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes…
[FIX] html_builder: fix job location editing on website Scenario: 1) Head over to website 2) Go to any specific job page 3) Open editor 4) Try changing job location 5) Hit save Result: The changes aren't saved or propagated into the backend. Expectation: Users should be able to edit job locations via the editor on website and have those changes reflect on the site and job record. Cause: How elements were marked as savable was changed [in this IMP][1] to rely on `o_savable` rather than the savable selectors resource. As a result, elements which had the `o_not_editable` class, such as job location, did not have `o_savable` added to them. These elements were excluded from the builder's dirty-tracking for save. Therefore, editing the location didn't mark the element as changed and saving to drop the update. Fix: Remove `o_not_editable` from the location element on plugin setup so the field is now editable and savable through the builder option. This surfaced a second issue: when the location was set to "Remote", the element's content could be directly editable inline. Saving it that way disconnected the content from the job location field. This was fixed by adjusting the selector that determines when a many2one's content is editable inline. The result is the "Remote" case is handled consistently as changing to any other location. [1]: https://github.com/odoo/odoo/commit/f3c119dd034b4c3df9f392b0cdc66a1141662c25 Task-6311200 Forward-Port-Of: odoo/odoo#274731
#### Issue: When creating a reordering rule for a shared manufactured product in a multi-company database, saving the rule may raise an `AccessError` on `mrp.bom`. The orderpoint is still created, but the user sees a record-rule error if the product also has BoMs in companies that are not currently active. #### Example: A product is shared across multiple companies, and each company has its own BoM for that product. In the reproduced case, the active company has the correct variant Bo
Original PR description
#### Issue: When creating a reordering rule for a shared manufactured product in a multi-company database, saving the rule may raise an `AccessError` on `mrp.bom`. The orderpoint is still created,…
#### Issue: When creating a reordering rule for a shared manufactured product in a multi-company database, saving the rule may raise an `AccessError` on `mrp.bom`. The orderpoint is still created, but the user sees a record-rule error if the product also has BoMs in companies that are not currently active. #### Example: A product is shared across multiple companies, and each company has its own BoM for that product. In the reproduced case, the active company has the correct variant BoM. However, the orderpoint computation first checks the broader product-template BoM relation, which may include BoMs from the other companies. As a result, Odoo can try to access a BoM from another company while the user is only working in the active company, causing an access error. #### Steps to reproduce: Use a multi-company database with MRP enabled. Create or use a shared product available to multiple companies. Create BoMs for that product in more than one company. Set the active company to the company where the reordering rule should be created. Create a reordering rule for the product. Save the reordering rule. Note the AccessError related to mrp.bom. #### Root Cause: The MRP orderpoint computations read `product_id.bom_ids` directly. This is the product-template BoM relation and can include BoMs from other companies for a shared product. Reading fields on those BoMs, such as `product_uom_id`, can hit the standard `mrp.bom` multi-company record rule. #### Fix: Prefer `product_id.variant_bom_ids` before falling back to `product_id.bom_ids` in the affected orderpoint computations. This avoids reading template-level BoMs from other companies when the product has a variant-specific BoM for the current reordering-rule use case. opw-6253743 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#275493 Forward-Port-Of: odoo/odoo#267411
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by
Original PR description
When a product uses automated inventory valuation, scrapping it from an already validated (done) picking generated no inventory valuation journal entry, even though the stock move value and the on-hand quantity were correctly updated. The same scrap done from the Scrap menu, or from a picking that is not done yet, worked as expected. A stock move whose picking is already done is created directly in the 'done' state (stock.move.create). Such a move is filtered out of the recordset returned by _action_done(), on which _create_account_move() is called, so the scrap move never received its journal entry. Steps to reproduce: - Use a storable product with automated inventory valuation - Create and validate a receipt for it - Open the completed picking, click Scrap, set a quantity and validate it - The stock is reduced but no journal entry is created. opw-6368258 Forward-Port-Of: odoo/odoo#275847
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
**Problem**: When a stock move has no quantity, the computation of the lot cost fails because it tries to divide by zero. **Fix**: Add a check to the ```move._get_valued_qty()``` to make sure it is not zero before performing the division. **Steps to reproduce:** 1. Create a product tracks quantity by lot, and valuation by Lot/Serial. 2. Assign a FIFO costing method category to it. 3. Update on hand quantity to 10 4. Reduce the on hand quantity to 5 and update to 10 again. 5. Go to t
Original PR description
**Problem**: When a stock move has no quantity, the computation of the lot cost fails because it tries to divide by zero. **Fix**: Add a check to the ```move._get_valued_qty()``` to make sure it is not zero before performing the division. **Steps to reproduce:** 1. Create a product tracks quantity by lot, and valuation by Lot/Serial. 2. Assign a FIFO costing method category to it. 3. Update on hand quantity to 10 4. Reduce the on hand quantity to 5 and update to 10 again. 5. Go to the in/out smart button and change the quantity of the most recent sml to 0. 6. Updating the on hand quantity to any larger number raises the error. **Notes**: This issue is created by the recent pr https://github.com/odoo/odoo/pull/273728. If a database has the same workflow before the commit, the error will be raised when checking the on hand quantity or trying to make a stock.picking of that product after checking out the commit. opw-6400941 Forward-Port-Of: odoo/odoo#277878
Unlocking a validated MO to add a new component move should, naturally, bring about a validated move. Although there exists a `state` check in `stock.move`'s `create()` as of odoo/odoo#196161, it only checks for `picking_id`, whereas a component move has a `raw_material_production_id` (and a finished (by)product has a `production_id`), so we replicate the check here. Task ID: [6226710](https://www.odoo.com/odoo/project/966/tasks/6226710)
Original PR description
Unlocking a validated MO to add a new component move should, naturally, bring about a validated move. Although there exists a `state` check in `stock.move`'s `create()` as of odoo/odoo#196161, it only checks for `picking_id`, whereas a component move has a `raw_material_production_id` (and a finished (by)product has a `production_id`), so we replicate the check here. Task ID: [6226710](https://www.odoo.com/odoo/project/966/tasks/6226710)
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content bel
Original PR description
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content below to be pushed down. **Fix:** Moved the banner inside the call window, but only when it is not compact (not in smaller chat window or mobile). Could fix with css but we probably don't want to show the banner in these cases anyway (as it would take too much space in the chat window, or not be relevant to mobile users). [1] https://github.com/odoo/odoo/commit/d45c92eb07cd16cc45b0e9c8bf9422fe974f0c62 opw-6250056 Forward-Port-Of: odoo/odoo#278804 Forward-Port-Of: odoo/odoo#277982
Miscellaneous changes
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a large number of `hr.employee` records. Specifically, when running `test_mock_crawl` and mocking the `Attendances > Reporting > Time Off Ledger` menu. PostgreSQL mis-estimated the row counts produced by the view: - The public-holiday check combined an `OR` with a function-wrapped `BETWEEN` (
Original PR description
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a…
On a production-sized database the `hr.leave.attendance.report` SQL view took over three hours to run. This caused a significant load on the upgrade platform when processing databases that have a large number of `hr.employee` records. Specifically, when running `test_mock_crawl` and mocking the `Attendances > Reporting > Time Off Ledger` menu. PostgreSQL mis-estimated the row counts produced by the view: - The public-holiday check combined an `OR` with a function-wrapped `BETWEEN` (`... AT TIME ZONE ... ::date`), which the planner cannot estimate; it predicted ~1 surviving row (actual: 29.4M) and chose nested loops that re-aggregated whole tables once per output row. - The attendance sub-query aggregated the entire `hr_attendance` table with no date bound, and was re-executed per output row. - The working schedule was resolved with a per-(employee, day) `LIMIT 1` lookup into `hr_version` (29.4M index probes). Rewrite the view as a set of CTEs: every heavy table is scanned once, joins use plain equality keys (hash-joinable), public holidays are pre-expanded so their exclusion stays an anti-join, the attendance aggregate is bounded to the report window, and hr_version is resolved by expanding each version over the days it covers. None of the CTEs are explicitly materialized: left to its own heuristic, PostgreSQL inlines a CTE referenced only once as a plain subquery and materializes the ones referenced more than once, which benchmarked faster than forcing materialization everywhere. This rewrites the body of the SQL view only: no schema change, no new field, no index, no migration. The report output is unchanged. Measured with EXPLAIN (ANALYZE, BUFFERS) on the same database: | metric | before | after | factor | |----------------|---------------|----------|--------| | execution time | 11 852 235 ms | 1 834 ms | ~6500x | | buffer hits | 115 311 556 | 71 890 | ~1600x | upg-4288902 Forward-Port-Of: odoo/odoo#266108
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results direct
Original PR description
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the…
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results directly in the relevant dicts. --- ### Batch and prefetch for initial product std_price **Problem:** When initializing products' standard price before replaying valuation, the first stock.move is read. This happens before any prefetching or batching occurs, so a query is made per move and contributes to performance issues. **Solution:** Batch and prefetch the products' first moves, then initialize the standard price. --- ### Use cached is_in and is_out values **Problem:** In `_get_valued_qty()`, `_is_in()` and `_is_out()` are called for each move, but these methods are already called for these moves and cached as `is_in` and `is_out`. **Solution:** Replace the method calls with the cached fields. If the move is not done, we fallback to the methods as the cached fields will be false for not done moves. --- **Perf Tables:** Record: product.template, each with AVCO automated valuation and a done in move Today: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |1.08s |264 |697ms |235 | |5k |2.74s |864 |2.23s |864 | |10k |4.83s |1375 |4.56s |1870 | At Date: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |3.10s |6109 |925ms |386 | |5k |14.68s |30299 |3.50s |1564 | |10k |26.98s |59173 |7.16s |3590 | opw-6134244 Forward-Port-Of: odoo/odoo#261624
6 changes
Resolved issues and error corrections
e39bf6c6ab31e57d472a552cb9b902496e6323ae introduced a blacklist to email sending, to filter out "alias emails" (catchall...) & the root partner email (odoobot) from being sent certain emails, such as mailings. By default, odoobot email is odoobot@example.com. However, there are cases where users will have a legitimate partner that matches the odoobot email; an example of this is saas config, which automatically changes the odoobot email to the admin email set on database spin-up. This
Original PR description
e39bf6c6ab31e57d472a552cb9b902496e6323ae introduced a blacklist to email sending, to filter out "alias emails" (catchall...) & the root partner email (odoobot) from being sent certain emails, such as mailings. By default, odoobot email is odoobot@example.com. However, there are cases where users will have a legitimate partner that matches the odoobot email; an example of this is saas config, which automatically changes the odoobot email to the admin email set on database spin-up. This prevents the database admin from receiving their own mailings. To fix this, the root partner email is now only added to the blacklist if no active partner has the same email. Steps to reproduce: - Add a mailing contact with the same email as the root partner - Send a mailing to that mailing contact task-4893615 Forward-Port-Of: odoo/odoo#278122 Forward-Port-Of: odoo/odoo#264112
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content bel
Original PR description
**Steps to reproduce:** - Go to Discuss app - Start a new meeting - Enable Push-To-Talk in voice settings - A banner for the discuss extension recommendation is added the first time you enable the setting - Banner makes the call window move down - Call actions are pushed to the bottom of the screen and not easily accessible **Issue:** An ad banner for the Push-To-Talk extension was added by [1], but it was inserted above the call window rather than on top of it, causing the content below to be pushed down. **Fix:** Moved the banner inside the call window, but only when it is not compact (not in smaller chat window or mobile). Could fix with css but we probably don't want to show the banner in these cases anyway (as it would take too much space in the chat window, or not be relevant to mobile users). [1] https://github.com/odoo/odoo/commit/d45c92eb07cd16cc45b0e9c8bf9422fe974f0c62 opw-6250056 Forward-Port-Of: odoo/odoo#277982
When receiving a Peppol/UBL XML file containing an embedded PDF via an email alias, the PDF is not extracted and attached to the resulting vendor bill. Steps to reproduce: - Set up a BE Company - Configure an incoming mail server - Set up an email alias for the Vendor Bill journal - Receive a Peppol XML with embedded PDF via alias - Check the created Bill Issue: PDF has not been extracted from the xml This occurs because the received xml is set as main attachment for the record a
Original PR description
When receiving a Peppol/UBL XML file containing an embedded PDF via an email alias, the PDF is not extracted and attached to the resulting vendor bill. Steps to reproduce: - Set up a BE Company - Configure an incoming mail server - Set up an email alias for the Vendor Bill journal - Receive a Peppol XML with embedded PDF via alias - Check the created Bill Issue: PDF has not been extracted from the xml This occurs because the received xml is set as main attachment for the record and in this case we skip extraction opw-6075250 Forward-Port-Of: odoo/odoo#278428 Forward-Port-Of: odoo/odoo#262047
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188
Original PR description
The mock server was computing the reaction sequence with `Math.min(reactionGroup.map(...))` instead of `Math.min(...reactionGroup.map(...))`. This returned `NaN`, making the sort order non-deterministic and causing the 'Reactions are ordered by id' test to be flaky. Fixes runbot error https://runbot.odoo.com/odoo/error/944188
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Original PR description
A space in the front, Trimmed away to left-align Thanks for reviewing See opw-6386651 Forward-Port-Of: odoo/odoo#278021
Miscellaneous changes
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results direct
Original PR description
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the…
### Batch per all moves, not per product **Problem:** In https://github.com/odoo/odoo/pull/250526, moves are batched in order to prevent memory error in databases with many stock.move. However, the batching is done on the moves per product, meaning batches can be very small relative to the limit, and this causes unecessary queries compared to batching per all moves to process. **Solution:** Iterate through all moves rather than per product, and use/save the per product results directly in the relevant dicts. --- ### Batch and prefetch for initial product std_price **Problem:** When initializing products' standard price before replaying valuation, the first stock.move is read. This happens before any prefetching or batching occurs, so a query is made per move and contributes to performance issues. **Solution:** Batch and prefetch the products' first moves, then initialize the standard price. --- ### Use cached is_in and is_out values **Problem:** In `_get_valued_qty()`, `_is_in()` and `_is_out()` are called for each move, but these methods are already called for these moves and cached as `is_in` and `is_out`. **Solution:** Replace the method calls with the cached fields. If the move is not done, we fallback to the methods as the cached fields will be false for not done moves. --- **Perf Tables:** Record: product.template, each with AVCO automated valuation and a done in move Today: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |1.08s |264 |697ms |235 | |5k |2.74s |864 |2.23s |864 | |10k |4.83s |1375 |4.56s |1870 | At Date: |Record count|Time before|Queries before|Time after|Queries after| |------------|-----------|--------------|----------|-------------| |1k |3.10s |6109 |925ms |386 | |5k |14.68s |30299 |3.50s |1564 | |10k |26.98s |59173 |7.16s |3590 | opw-6134244 Forward-Port-Of: odoo/odoo#261624
3 changes
Enhancements to existing features
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Chan
Original PR description
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Change Password URL specification by exposing a public route that redirects to `/web/reset_password`. Reference: https://wicg.github.io/change-password-url/ --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277575
Resolved issues and error corrections
Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0: Internal compiler error #12345: error mmapping datablock to 30283637 Root cause: the accumulated size of `.po` files across all modules has grown past a threshold where the NSIS solid compressor tries to mmap a buffer larger than the ~2 GiB address space available to the 32-bit makensis running under Wine. Simply dropping the `/SOLID` option makes the build pass but nearly doubl
Original PR description
Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0: Internal compiler error #12345: error mmapping datablock to 30283637 Root cause: the…
Windows nightly builds have been failing for several days with this obscure NSIS error message in Odoo 19.0:
Internal compiler error #12345: error mmapping datablock to 30283637
Root cause: the accumulated size of `.po` files across all modules has grown past a threshold where the NSIS solid compressor tries to mmap a buffer larger than the ~2 GiB address space available to the 32-bit makensis running under Wine. Simply dropping the `/SOLID` option makes the build pass but nearly doubles the size of the final installer, which is not acceptable.
The chosen fix is to pre-bundle all `.po` files into a single solid 7z archive and extract it at install time using the `Nsis7z` plugin. This keeps the NSIS datablock well below the and yields comparable or better final installer size than the previous approach, along with faster build times.
While at it, this commit also modernizes the Windows build environment to unblock a separate wine-devel install regression that has been affecting Odoo 17.0 nightlies on Debian Bookworm.
Changes:
- Bundle `.po` files into `i18n_bundle.7z` inside the build container prior to invoking makensis; extract it at install time via the `Nsis7z` plugin.
- Bump the base image from Debian Bookworm to Trixie.
- Switch from `wine-devel` to `wine-stable`, which resolves the install regression on Bookworm-based builds.
- Upgrade NSIS to the latest release.
- Refactor the NSIS installation step to remove the hardcoded version from `package.py`.
This fix is made in Odoo 17.0 to unblock the wine-devel issue there and to benefit from the smaller installer size on supported stable branches.
Forward-Port-Of: odoo/odoo#278378odoo/odoo#155588 was a workaround to the lack of location permissions in the iOS app, skipping geolocation entirely for check in/out. Since odoo/mobile#118 added support for them, we can now revert that fix so iOS users get prompted for their location again. task-6279460 Forward-Port-Of: odoo/odoo#277167 Forward-Port-Of: odoo/odoo#276934
Original PR description
odoo/odoo#155588 was a workaround to the lack of location permissions in the iOS app, skipping geolocation entirely for check in/out. Since odoo/mobile#118 added support for them, we can now revert that fix so iOS users get prompted for their location again. task-6279460 Forward-Port-Of: odoo/odoo#277167 Forward-Port-Of: odoo/odoo#276934
8 changes
Enhancements to existing features
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Chan
Original PR description
Password managers and browsers rely on the standardized `/.well-known/change-password` URL to automatically locate a site's password change form, instead of relying on unreliable heuristics to detect it inside the page. Without this endpoint, users depending on password manager integrations (Chrome, Safari, 1Password, Bitwarden, etc) have no reliable way to be redirected to the actual reset form, resulting in a degraded UX and inconsistent behavior across browsers. This implements the Change Password URL specification by exposing a public route that redirects to `/web/reset_password`. Reference: https://wicg.github.io/change-password-url/ --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277575
Resolved issues and error corrections
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will disappear when it's gone it will throw a user error, without the MO reappearing. Steps to reproduce --------------------------- **Issue 1** 1) Create a product "final" 2) Create a product "component" tracked by lot 3) Update the on hand quantity and don't assign a lot number 4) Create a BoM
Original PR description
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will…
For an MO with component tracked by lot is possible to close it without assigning the lot number even when they are marked for manual consumption. From the shopfloor this will close the MO that will disappear when it's gone it will throw a user error, without the MO reappearing. Steps to reproduce --------------------------- **Issue 1** 1) Create a product "final" 2) Create a product "component" tracked by lot 3) Update the on hand quantity and don't assign a lot number 4) Create a BoM for "final" with "component" as component and manual consumption 5) Create a MO and confirm it 6) Go to shopfloor 7) Set "final" quantity 8) Set "component" quantity 10) Close the MO -> The MO disappear (leaving a user error) -> Since the "component" does not have a lot number it should not disappear **Issue 2** Same steps as Issue 1 until step 6: 6*) Add "comp" as barcode to the product component 7*) Go to barcode 8*) Open the manufacturing order 9*) Add the quantity to final 10*) Scan "comp" 11*) Scan a non-existent lot number, ex: "12345" -> It raise the error Observation ---------------------- **Issue 1** When clicking on "Closing production" it will call [onClickValidateButton](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L481-L482)() that will lead us to validate, and validate will [call](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L511) the function [pre_button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L507) in python. in pre_button_mark_done, we will skip any check on the lot number, since we already have set qty_producing (when setting "final" quantity), it will avoid _set_quantities where a check for lot number is made: https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2235-L2239 https://github.com/odoo/odoo/blob/9218d302b0fd56c1854d95d3756c0f5e9c9c8700/addons/mrp/models/mrp_production.py#L2839-L2844 And it will also skip the consumption wizard since it doesn't check for lot number nor allow to set lot numbers: https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/mrp/models/mrp_production.py#L1658-L1660 After avoiding both checks we go back to validate. In validate and we update the variable underValidation which will [trigger the fadeout animation](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L154) When the [animation ends](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L662-L665), the call to realValidation will be triggered and will call productionValidation that will send a call to [button_mark_done](https://github.com/odoo/enterprise/blob/37b21f93828fae2caec87cfd8413e144751eefc0/mrp_workorder/static/src/mrp_display/mrp_display_record.js#L551) In button_mark_done, when calling _action_done on the move_lines, we will finally check that there is a lot number, which will trigger an error : https://github.com/odoo/odoo/blob/35f804995118e6ffe150c9c7a7bad4844bd0e0ed/addons/stock/models/stock_move_line.py#L664-L669 but because the fadeout animation is already over, the mo will have disappeared, which means we can't correct the userError that has been raised. **Issue 2** In barcode when scanning a lot after a product, it will not create a lot but only apply a lot_name : https://github.com/odoo/enterprise/blob/7b57a2927aeb8abf84d0f6acc64a7e9bbc8f608d/stock_barcode/static/src/models/barcode_model.js#L1306-L1311 this cause an issue with the existing condition since it only pass the check if there is a lot, but in this case there only is a lot_name. When we click on "Produce" in a Mo in barcode, it will call validate, that in this case, will call button_mark_done: https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/components/main.xml#L163 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode/static/src/models/barcode_model.js#L602-L605 https://github.com/odoo/enterprise/blob/80aaa507fd2196b90cea724ecab0fa0ed5f13db6/stock_barcode_mrp/static/src/models/barcode_mrp_model.js#L14 opw-6060310
### Steps to Reproduce: 1. Make sure that the Sale and Inventory modules are installed 2. Enable Multi-Step Routes and Packages in Inventory Configurations 3. Warehouse configuration > Outgoing shipments > Select Pick then Deliver (2 steps) 4. Routes > Deliver in 2 steps (pick + ship) > Pull From > Destination Location > Select WH/Output 5. Routes > Deliver in 2 steps (pick + ship) > Push To > Action > Change to Pull From 6. Operation Types > Delivery Orders > Packages > Enable Move Entire
Original PR description
### Steps to Reproduce: 1. Make sure that the Sale and Inventory modules are installed 2. Enable Multi-Step Routes and Packages in Inventory Configurations 3. Warehouse configuration > Outgoing…
### Steps to Reproduce: 1. Make sure that the Sale and Inventory modules are installed 2. Enable Multi-Step Routes and Packages in Inventory Configurations 3. Warehouse configuration > Outgoing shipments > Select Pick then Deliver (2 steps) 4. Routes > Deliver in 2 steps (pick + ship) > Pull From > Destination Location > Select WH/Output 5. Routes > Deliver in 2 steps (pick + ship) > Push To > Action > Change to Pull From 6. Operation Types > Delivery Orders > Packages > Enable Move Entire Packages 7. Go to any product, ex. Drawer > On Hand > Set original on hand qty to 16 and new lot to 50 8. Create a new SO and make 2 lines, with the same product, and change the second line's price to something else, ex. 80.0 9. Deliveries > WH/PICK/00001 > Set quantity to 4 > Put in Pack > Validate and Create Backorder 10. WH/PICK/00002 > Put in Pack > Validate 11. WH/OUT/00012 > Mark PACK0000001 Done > Save. Observe how the first line quantity is changed from 3 to 4 12. Mark PACK0000002 Done > Save > Validate > Observe how it's asking for a backorder even though we already packed all 5 items. ### Description of the issue/feature this PR addresses: Instead of using the `product_qty` from the stock move, use the quantity of the move line to correctly allocate the quantities in StockPackageLevel ### Current behavior before PR: In the Shop Floor when loading packages, marking the package level as done causes issues on the quantity processed on the corresponding move lines. On stock transfers, we currently allocate the Quantity Done to the wrong product line. The total quantity is correct, but the distribution across lines does not match the Demand values. This causes the transfer to remain stuck in Reserved, even though the shipment was already processed operationally. ### Desired behavior after PR is merged: The correct quantity from the move line is used and this resolves the issue with quantity distribution not matching move line quantities when using packages. opw-6040640 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
### Steps to reproduce: - Create 3 AVCO products: Super Kit, Kit, Comp - Super Kit BoM: 2 x Kit - Kit BoM: 1 x Comp - Create and confirm a purchase order for 1 X Super Kit at 100 - Validate the receipt of 2 Comp - Go to the valuation > Both units of Comp are valued at 100 for a total of 200 ### Cause of the issue: The issue has been introduced by: https://github.com/odoo/odoo/pull/158849/changes/713701a5035d342263e3fef2a2819b5696b6d063 To be more precise, the price unit of each u
Original PR description
### Steps to reproduce: - Create 3 AVCO products: Super Kit, Kit, Comp - Super Kit BoM: 2 x Kit - Kit BoM: 1 x Comp - Create and confirm a purchase order for 1 X Super Kit at 100 - Validate the…
### Steps to reproduce: - Create 3 AVCO products: Super Kit, Kit, Comp - Super Kit BoM: 2 x Kit - Kit BoM: 1 x Comp - Create and confirm a purchase order for 1 X Super Kit at 100 - Validate the receipt of 2 Comp - Go to the valuation > Both units of Comp are valued at 100 for a total of 200 ### Cause of the issue: The issue has been introduced by: https://github.com/odoo/odoo/pull/158849/changes/713701a5035d342263e3fef2a2819b5696b6d063 To be more precise, the price unit of each unit of Comp is expected to be computed by the `_get_price_unit`. This method used to rely on the `product_qty` appropriately: https://github.com/odoo/odoo/pull/158849/changes/713701a5035d342263e3fef2a2819b5696b6d063#diff-687527af1723e60816358020c4d83687479df62ca0cfd71079f0a82afb4b3efeL27 However, backorder adapt the move demand and hence did not provide the appropriate demand in this flow that computation logic was changed to rely on the `bom` and `bom_line` quantities: https://github.com/odoo/odoo/blob/29977a6a80442af49ecefa7fef54f085483d8f77/addons/purchase_mrp/models/stock_move.py#L20-L40 This new computation is not correct in case of nested boms since the `bom_line` only carries the unit demand on the last explosion stage. ### Additional issue: If nested kit boms lead to the creation of 2 moves with the same `cost_share` and `bom_line_id`, these moves will be merged without summing their `cost_share` leading to an under pricing of the kit since its related `stock_move`'s `cost_share` will not sum up to 100 percents anymore. This issue is tested in `test_avco_purchase_nested_kit_explode_cost_share_backorder_2` and fixed similarly to demand merging: https://github.com/odoo/odoo/blob/613f3cb7b2f4813ce6c8f53718a6cca841b081ad/addons/stock/models/stock_move.py#L1122-L1134 ### Note: We also modify the test `test_valuation_with_backorder` to be understandable and to make appropriate asserts. opw-6253776 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
**Steps to reproduce:** (Firefox only) - Go to any chatter - Open the full composer - Try to add a link (using `/link` or by selecting existing text and using the toolbar) - Change a value in the popup - On each input the cursor gets back to the editor and you need to manually move it back to type again **Issue:** When inside a modal (Full Composer), the autofocus hook in the `LinkPopover` setup does not behave as expected. The active element is assigned to the modal container
Original PR description
**Steps to reproduce:** (Firefox only) - Go to any chatter - Open the full composer - Try to add a link (using `/link` or by selecting existing text and using the toolbar) - Change a value in the popup - On each input the cursor gets back to the editor and you need to manually move it back to type again **Issue:** When inside a modal (Full Composer), the autofocus hook in the `LinkPopover` setup does not behave as expected. The active element is assigned to the modal container instead of the input element inside the popover, which does not receive focus. **Fix:** Backporting autofocus fix from [1]. [1] https://github.com/odoo/odoo/commit/927fa045e1565a39ef6cb2c9b241686c62c234fe opw-6344131
With "Round Globally" tax rounding, invoicing a 100% down payment and then creating the final regular invoice yields a credit note of 0.01 instead of an invoice of 0.00. The sales order is still flagged as fully invoiced, so the customer is left with an unexpected refund document. A down payment line can only store a `price_unit` rounded to the 'Product Price' decimal precision, while the product lines it must offset are aggregated from their raw amounts. When a product subtotal falls on a ha
Original PR description
With "Round Globally" tax rounding, invoicing a 100% down payment and then creating the final regular invoice yields a credit note of 0.01 instead of an invoice of 0.00. The sales order is still…
With "Round Globally" tax rounding, invoicing a 100% down payment and then creating the final regular invoice yields a credit note of 0.01 instead of an invoice of 0.00. The sales order is still flagged as fully invoiced, so the customer is left with an unexpected refund document. A down payment line can only store a `price_unit` rounded to the 'Product Price' decimal precision, while the product lines it must offset are aggregated from their raw amounts. When a product subtotal falls on a half cent (e.g. quantity 0.5 at 1.01 => 0.505), the final invoice carries a raw residual of -0.005. `_round_tax_details_base_lines` rounds that aggregate to -0.01 and `_distribute_delta_amount_smoothly` assigns the cent to the largest base line, leaving its `balance` one cent away from its own `price_subtotal`. Since `amount_untaxed` derives from the balances, the invoice totals -0.01 and `_create_invoices` switches it to a refund. The product amounts have already been invoiced and rounded on the down payment invoice, so the aggregation must target those rounded amounts. Declare them through `manual_total_excluded_currency`, which is read from the base line dict and feeds `target_total_excluded`. `total_excluded` is unchanged, so no posted or displayed amount moves. 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
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back
Original PR description
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is…
Steps to reproduce --- 1. Confirm a purchase order and receive it a few days later. 2. Open Purchase, Reporting, Purchase and add the "Effective Days To Arrival" measure. Observed: the value is counted from the line's scheduled date instead of the order date, and can even be negative when the scheduled date precedes the confirmation date. Issue --- The metric is meant to be the effective lead time, the number of days between the order confirmation and the actual receipt, falling back to the planned "days to receive" when nothing has been received yet according to [task](https://www.odoo.com/odoo/project/809/tasks/3691573). The query instead computes age(date_planned, COALESCE(date_done, date_order)), so once a receipt exists it returns date_planned - date_done (the gap between the scheduled date and the receipt) rather than date_done - date_order. https://github.com/odoo/odoo/blob/c06be48ce7277a667719fd756e0a1f63e91cda27/addons/purchase_stock/report/purchase_report.py#L20-L28 opw-6226523
Issue ----- Adding packagings of products through the catalog sometimes doesn't work. Steps to reproduce ----- - Create multiple products with some packaging - Create a PO - Open the product catalog - Add products & packagings (click the product then the pack button) - Go back to the PO => Some lines might not have the packaging but instead a single unit Cause ----- The problem is a race condition with the `/product/catalog/update_order_line_info` route https://github.com
Original PR description
Issue ----- Adding packagings of products through the catalog sometimes doesn't work. Steps to reproduce ----- - Create multiple products with some packaging - Create a PO - Open the product catalog…
Issue ----- Adding packagings of products through the catalog sometimes doesn't work. Steps to reproduce ----- - Create multiple products with some packaging - Create a PO - Open the product catalog - Add products & packagings (click the product then the pack button) - Go back to the PO => Some lines might not have the packaging but instead a single unit Cause ----- The problem is a race condition with the `/product/catalog/update_order_line_info` route https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/product/controllers/catalog.py#L32-L33 The problem comes from the call to `_update_order_line_info` where the bahviour is different depending on the order in which the calls are treated. https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/purchase/models/purchase_order.py#L1195-L1238 The expected flow is for the call to add the product to be treated first, then the call to add the packaging. If the order of the calls is reversed, the packaging call does not go into either of the conditions and nothing happens, then the "add product" call is handled and a line for a single unit is created. This is caused by the JS where the "add product" calls are handled in order by processing them in a promise queue https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/product/static/src/product_catalog/kanban_record.js#L68-L78 The "packaging" calls, however, are fired directly, meaning there is no guarantee the line has already been created. https://github.com/odoo/odoo/blob/427d398880c381981e088f7001f855a10d1cd581/addons/purchase/static/src/product_catalog/kanban_record.js#L34-L47 ----- Ticket: opw-6401919
2 changes
Resolved issues and error corrections
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1- Create two auto detect fiscal positions: France, Germany 2- Set portal user's partner address country to France. 3- Using portal user, shop from website, and create a delivery address. 4- Pay and confirm the order. 5- Using the admin user, you check the SO's FP which is correctly set to
Original PR description
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1-…
Issue: --- Fiscal position is wrongly set to `self.env.user.partner_id.country_id` instead of `partner_shipping` country, if `partner_shipping_id` is not changed in the checkout process. Steps: 1- Create two auto detect fiscal positions: France, Germany 2- Set portal user's partner address country to France. 3- Using portal user, shop from website, and create a delivery address. 4- Pay and confirm the order. 5- Using the admin user, you check the SO's FP which is correctly set to Germany. 6- Using portal user, again shop from website, and don't change address. Keep previous shipping address which is Germany. 7- Confirm and pay the order. 8- Using admin user, check the new SO's FP. It's set to France. Cause: --- `_compute_fiscal_position_id` in SO depends on `partner_shipping_id`. When the `partner_shipping_id` is not changed, the fiscal position value set in create will remain. This value is set in `Website._prepare_sale_order_values()`. The `fiscal_position_id` is set to self.fiscal_position_id, which is `_get_fiscal_position(self.env.user.partner_id)`. Fix: --- If the user has already a SO, we can use last SO's shipping address and invoice address to calculate FP in `_prepare_sale_order_values`. opw-6357638
### Steps to Reproduce: 1. Go to login page and click "Don't have an account?" 2. Create an account with a space in the email 3. Try to login with just the email with no space -> fail 4. Log in with the space -> success ### Description of the issue/feature this PR addresses: **Issue:** There is no email validation that occurs when users create a new account. Therefore, if they accidentally add a space to the email, they have to login with the space or change their login. However, there
Original PR description
### Steps to Reproduce: 1. Go to login page and click "Don't have an account?" 2. Create an account with a space in the email 3. Try to login with just the email with no space -> fail 4. Log in with…
### Steps to Reproduce: 1. Go to login page and click "Don't have an account?" 2. Create an account with a space in the email 3. Try to login with just the email with no space -> fail 4. Log in with the space -> success ### Description of the issue/feature this PR addresses: **Issue:** There is no email validation that occurs when users create a new account. Therefore, if they accidentally add a space to the email, they have to login with the space or change their login. However, there are also users who use this field as a username, rather than an email. **Solution:** Make email validation upon account creation optional as a new `ir.config.parameter`. This way, users can choose whether they want to use the email field as a validated email or just a username. ### Current behavior before PR: Since emails are validated, if users accidentally add special characters to their email when signing up, they have to include it every time they login, unless they manually change their login. ### Desired behavior after PR: There will be no email validation by default, but users can activate it (and deactivate if they change their mind in the future). There will be a new `ir.config.parameter` called `auth_signup.validate_email`. opw-6378031 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr