Daily updates from Odoo
Wednesday, July 29, 2026
235 changes
28 changes
Enhancements to existing features
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#277088 Forward-Port-Of: odoo/odoo#251797
Original PR description
It is mandatory in BE to add a legal note on the invoice when using a "Co-Contractant" tax task-5905176 Forward-Port-Of: odoo/odoo#277088 Forward-Port-Of: odoo/odoo#251797
Resolved issues and error corrections
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for Lot/Serial in the notification systray should apply the Late activities filter. ## Steps to reproduce: 1. Install Inventory (stock) module, make sure to enable Lots & Serial Numbers in Inventory > Traceability 2. Create some new Lots / Serial numbers 3. Add some Activities with Due Date before to
Original PR description
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for…
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for Lot/Serial in the notification systray should apply the Late activities filter. ## Steps to reproduce: 1. Install Inventory (stock) module, make sure to enable Lots & Serial Numbers in Inventory > Traceability 2. Create some new Lots / Serial numbers 3. Add some Activities with Due Date before today 4. Observe that the Clock icon on systray will count up, showing the number of activities that are late, for today and for future 5. Click on the Late activities (e.g. 2 Late) should only show the 2 late activities. Instead, no filter is applied, thus showing all the Lots / Serial numbers in the inventory ## Cause of the issue: Missing filters for Late, Today and Future activities in the stock_lot_views.xml ## Fix: Added 3 filters for Late, Today and Future activities opw-6332560 Forward-Port-Of: odoo/odoo#278165 Forward-Port-Of: odoo/odoo#272735
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
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the return
Original PR description
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem:…
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the returned combination was correct. The 0.5s threshold is an arbitrary sanity check meant to catch a gross algorithmic regression (e.g. loss of early pruning of invalid combinations), not a strict performance SLA, so it is too tight to survive normal CI load variance. Solution: Raise the threshold to 2 seconds, keeping enough margin to absorb CI load variance while still catching a real performance regression, which would take far longer than the current computation. runbot-243606 Forward-Port-Of: odoo/odoo#277986
Steps to reproduce the bug: - Create a purchase requisition: - add any storable product and vendor - From it, create a purchase order and confirm it -> a picking is created - Cancel the "purchase.requisition" Problem: The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it. In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs,
Original PR description
Steps to reproduce the bug:
- Create a purchase requisition:
- add any storable product and vendor
- From it, create a purchase order and confirm it -> a picking is created
- Cancel the "purchase.requisition"
Problem:
The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it.
In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs, with no check on their current state or on whether picking or invoices existed.
Solution:
Only cancel linked purchase orders that are still in 'draft' state. Once
outside of that state, the purchase process might be too far engaged to
simply cancel the purchase order without notice.
opw-6329742
Forward-Port-Of: odoo/odoo#272190**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#278962 Forward-Port-Of: odoo/odoo#277982
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: . Add safe execution to the element before use focus() task-6409715 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278083
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: . Add safe execution to the element before use focus() task-6409715 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278083
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a decimal duration such as 5.01 days. This is inconsistent with half-day time off types, which should consume time in half-day increments. **Steps to reproduce:** - Create an employee with a fully fixed duration-based schedule - Set morning and afternoon attendances to 3.36 hours for each weekday
Original PR description
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a…
**Issue:** When an employee uses a fully fixed duration based working schedule and each half-day attendance has a decimal duration such as 3.36h, a multi-day half-day time off request can compute a decimal duration such as 5.01 days. This is inconsistent with half-day time off types, which should consume time in half-day increments. **Steps to reproduce:** - Create an employee with a fully fixed duration-based schedule - Set morning and afternoon attendances to 3.36 hours for each weekday - Create a time off type with duration type set to half-day - Create a time off request for the employee (e.g. Monday to Friday) - The computed duration is 5.01 days instead of 5 days **Cause:** For half-day time off types, `number_of_days` was taken from generic calendar interval computation. https://github.com/odoo/odoo/blob/19c0e59cc37c7671f13cbda1b2d4850a7731eade/addons/hr_holidays/models/hr_leave.py#L585-L593 On duration-based schedules, this computation returns day values rounded at 0.001 precision, so decimal drift (e.g. 5.01) can appear, Since no final rounding to half-day steps was applied, half-day requests could end with non-half-day values. **Solution:** Round computed durations for half-day time off types to the nearest half-day increment. opw-6215768 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278656 Forward-Port-Of: odoo/odoo#267726
When running test_catalog_price test, it checks for productUomFactor. However, when running single app tests, sometimes UOM is disabled, and productUomFactor won't be returned in that case. runbot-242515 Forward-Port-Of: odoo/odoo#276910
Original PR description
When running test_catalog_price test, it checks for productUomFactor. However, when running single app tests, sometimes UOM is disabled, and productUomFactor won't be returned in that case. runbot-242515 Forward-Port-Of: odoo/odoo#276910
[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#278777 Forward-Port-Of: odoo/odoo#274731
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
Original PR description
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
Original PR description
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a
Original PR description
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a non-Belgian company, and invoice from another active Belgian company. - Move every active user off the main company and archive it - Send a Belgian 0% invoice through the cron. => IndexError: tuple index out of range in chart_template.ref opw-6398778 Forward-Port-Of: odoo/odoo#278666 Forward-Port-Of: odoo/odoo#278326
The actions menu is cluttered with redundant presence actions. To streamline the UI, the presence actions have been removed from the root menu and are now kept exclusively within the "Presence Control" submenu. Steps to reproduce: 1. Navigate to an Employee record. 2. Open the Actions menu. 3. Observe that "Set Present", "Set Absent", "Send SMS", and "Create a Time Off" appear in the root menu AND in the "Presence Control" submenu. Furthermore, invoking these actions from the Presence C
Original PR description
The actions menu is cluttered with redundant presence actions. To streamline the UI, the presence actions have been removed from the root menu and are now kept exclusively within the "Presence…
The actions menu is cluttered with redundant presence actions. To streamline the UI, the presence actions have been removed from the root menu and are now kept exclusively within the "Presence Control" submenu. Steps to reproduce: 1. Navigate to an Employee record. 2. Open the Actions menu. 3. Observe that "Set Present", "Set Absent", "Send SMS", and "Create a Time Off" appear in the root menu AND in the "Presence Control" submenu. Furthermore, invoking these actions from the Presence Control submenu did not pass the correct record context. Because of this, dialogs like "Create a Time Off" failed to automatically prefill with the currently selected employee's data, disrupting the workflow. 1. Navigate to an Employee record. 2. Open the Actions menu and hover over the "Presence Control" submenu. 3. Click "Create a Time Off". 4. Observe that the employee field in the dialog is blank instead of prefilling with the current employee. task-6384993 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
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#278737 Forward-Port-Of: odoo/odoo#277813
Issue: The unreserve button in forecast is no longer visible. Steps to Reproduce: 1. Create an MO for a product that has a storable component 2. Confirm the MO 3. Go to the component product form 4. Click on the forecast smart button Cause: After this commit, https://github.com/odoo/odoo/commit/df40bc9e261a62c045e7e6150a60663a582e7dae to support Owl3, the code was breaking because we were no longer passing line_index through `this`. Solution: Since the variable `line_index` was n
Original PR description
Issue: The unreserve button in forecast is no longer visible. Steps to Reproduce: 1. Create an MO for a product that has a storable component 2. Confirm the MO 3. Go to the component product form 4. Click on the forecast smart button Cause: After this commit, https://github.com/odoo/odoo/commit/df40bc9e261a62c045e7e6150a60663a582e7dae to support Owl3, the code was breaking because we were no longer passing line_index through `this`. Solution: Since the variable `line_index` was no longer available with `this`, we are now passing it as a parameter. opw-6317760 Forward-Port-Of: odoo/odoo#271322
# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in one language (Should be something like /shop/category/name-x) - Have two websites, each with a different default language - Create a link to the shop category in each website. > ! The link must be the exact same > You can put it in the header menu for simplicity - Open the website editor - D
Original PR description
# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in…
# How to reproduce
- Have two language in the db
- Create an e-Commerce category
- Have a different translation for each language for that category's name
- Copy the link to that category's name in one language (Should be something like /shop/category/name-x)
- Have two websites, each with a different default language
- Create a link to the shop category in each website.
> ! The link must be the exact same
> You can put it in the header menu for simplicity
- Open the website editor
- Do 2 or 3 times :
- click on the category link and switch website
# The issue
A traceback is displayed
# Cause
This manipulation will make us enter an infinite redirect scenario described here :
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/website/static/src/client_actions/website_preview/website_builder_action.js#L371-L384
The problem is that this commit introduced an assignation to `iframe.contentDocument.body` before the patch :
https://github.com/odoo/odoo/commit/89994eb7a54ca606bab26b6d579d03e86c11ba60
But in our case, iframe.contentDocument is null, so it throws an error before the patch can be applied
opw-6322115
Forward-Port-Of: odoo/odoo#276634# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job Position - Save # The problem If we go back to the contact, we can see it's name changed from X to Z. This is an expect behavior since : https://github.com/odoo/odoo/commit/c06aefa827bc00a14c9f8bd994d1831053cbf7af The issue lies in the fact that this change to the linked partner is not logged in
Original PR description
# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job…
# How to reproduce - In Contacts, Create a contact with name X and mail Y - Go to the Recruitment App > Applications > All Applications - Create a new Application with name Z, mail Y, any Job Position - Save # The problem If we go back to the contact, we can see it's name changed from X to Z. This is an expect behavior since : https://github.com/odoo/odoo/commit/c06aefa827bc00a14c9f8bd994d1831053cbf7af The issue lies in the fact that this change to the linked partner is not logged in the Applicant's form view. This may lead to contacts being unitentionally updated. # The cause `hr.applicant` inherits from 'mail.track.mixin', which correctly handles the logging in the chatter when editing an Applicant. However, the edition of the contact is triggered by an inverse function when creating the record, which is not handled by the inherited module : https://github.com/odoo/odoo/blob/af50cb24ac536e6afb14eee8221c69906191ba2b/addons/hr_recruitment/models/hr_applicant.py#L248-L253 # Proposed solution Use the `_track_record` method while tacking inspiration from : https://github.com/odoo/odoo/blob/3b5e4f558ccf9160e74e9e49ae324dd616241d61/addons/account/models/account_move_line.py#L2079 opw-6095671 Forward-Port-Of: odoo/odoo#271547
sale_loyalty filters amount_type == 'fixed' taxes when building discountable_per_tax in all three helpers: _discountable_order , _discountable_cheapest, _discountable_specific, so fixed taxes stay only on the original product line and are not transferred onto the discount reward line.
Original PR description
sale_loyalty filters amount_type == 'fixed' taxes when building discountable_per_tax in all three helpers: _discountable_order , _discountable_cheapest, _discountable_specific, so fixed taxes stay…
sale_loyalty filters amount_type == 'fixed' taxes when building discountable_per_tax in all three helpers: _discountable_order , _discountable_cheapest, _discountable_specific, so fixed taxes stay only on the original product line and are not transferred onto the discount reward line.
pos_loyalty has the equivalent filter on _getDiscountableOnOrder (pos_order.js:962, added in commit 68d35232dd5) but not on the two sibling methods. As a result, when a promotion program uses discount_applicability='cheapest' or 'specific', the fixed tax is copied onto the reward line's tax_ids and because the reward line carries a negative price its fixed-tax contribution cancels the same tax on the original product line, understating the order total.
This change ports the filter expression from _getDiscountableOnOrder to _getDiscountableOnCheapest and _getDiscountableOnSpecific, preserving the e-wallet / gift-card carve-out so those programs can still consume the full amount.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#267020
Forward-Port-Of: odoo/odoo#261370Once the cron is called to update current_version_id, the new employee calendar is applied to the previous version as well, due to the inverse on resource.resource def _inverse_calendar_id(self): for resource in self: if resource.calendar_id != resource.employee_id.resource_calendar_id: resource.employee_id.resource_calendar_id = resource.calendar_id All that because the introduced piece of code was called before super if 'current_versi
Original PR description
Once the cron is called to update current_version_id, the new employee calendar is applied to the previous version as well, due to the inverse on resource.resource
def _inverse_calendar_id(self):
for resource in self:
if resource.calendar_id != resource.employee_id.resource_calendar_id:
resource.employee_id.resource_calendar_id = resource.calendar_id
All that because the introduced piece of code was called before super
if 'current_version_id' in vals:
new_version = self.env['hr.version'].browse(vals.get('current_version_id'))
self.resource_id.calendar_id = new_version.resource_calendar_id
And this the inverse method was called on the previous version (not yet updated), not the new one.
Forward-Port-Of: odoo/odoo#279048## Problem When a `web_read_group` call is made with some condition on the active field, the active test is bypassed by adding `['active', 'in', [True, False]]` to the domain. This will cause a search to fail if the model's active field is not called `active` (like in a studio model). ## Solution We will change the domain to `[self._active_name, 'in', [True, False]]` to properly handle customizations. ## Steps to replicate (Runbot v19) 1. Create a new model with Studio - enable Pipeline
Original PR description
## Problem When a `web_read_group` call is made with some condition on the active field, the active test is bypassed by adding `['active', 'in', [True, False]]` to the domain. This will cause a search to fail if the model's active field is not called `active` (like in a studio model). ## Solution We will change the domain to `[self._active_name, 'in', [True, False]]` to properly handle customizations. ## Steps to replicate (Runbot v19) 1. Create a new model with Studio - enable Pipeline and Archiving 2. Open the kanban view and add 'Archived' to the filter 3. Traceback opw-6403422 Forward-Port-Of: odoo/odoo#277908 Forward-Port-Of: odoo/odoo#277666
When an order/invoice is fully discounted by a global discount, its base and tax amounts are sums of values each already rounded to the currency precision, so their sum is only a sub-unit floating point residue (~1e-6) instead of a clean zero. `_get_tax_totals_summary` fed that raw sum straight to the cash rounding. With a 'UP' (or 'DOWN') rounding method the residue was inflated into a full rounding step, e.g. a 0.01 total to pay on an otherwise empty document. opw-6402143 --- I confi
Original PR description
When an order/invoice is fully discounted by a global discount, its base and tax amounts are sums of values each already rounded to the currency precision, so their sum is only a sub-unit floating point residue (~1e-6) instead of a clean zero. `_get_tax_totals_summary` fed that raw sum straight to the cash rounding. With a 'UP' (or 'DOWN') rounding method the residue was inflated into a full rounding step, e.g. a 0.01 total to pay on an otherwise empty document. opw-6402143 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278291
When the shop sidebar categories are enabled with collapsed categories, subcategory names could wrap unexpectedly at 100% zoom or lower, even when there was enough available space. Steps to reproduce: - Open the Shop page and click Edit - Go to the Style tab - Set Content Width to Full - Enable the Categories sidebar - Enable Collapse Category This issue caused sidebar subcategory labels to wrap only at lower zoom levels, while higher zoom levels displayed them correctly. Add CSS
Original PR description
When the shop sidebar categories are enabled with collapsed categories, subcategory names could wrap unexpectedly at 100% zoom or lower, even when there was enough available space. Steps to reproduce: - Open the Shop page and click Edit - Go to the Style tab - Set Content Width to Full - Enable the Categories sidebar - Enable Collapse Category This issue caused sidebar subcategory labels to wrap only at lower zoom levels, while higher zoom levels displayed them correctly. Add CSS rules to prevent category names in the sidebar from wrapping. opw-6296804 Forward-Port-Of: odoo/odoo#275279
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#278806 Forward-Port-Of: odoo/odoo#262047
- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition. - Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position. runbot-error: 941390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-P
Original PR description
- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition.
- Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position.
runbot-error: 941390
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278813Miscellaneous 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#278690 Forward-Port-Of: odoo/odoo#266108
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA
Original PR description
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278542
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the m
Original PR description
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a…
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the many clients fan out over a much wider window and the registry recomputes spread over time instead of colliding. Raise the ceiling on the retry delay to two minutes to match that wider spread, and drop the exponential growth factor: with a thirty-second jitter accumulating on every attempt, the delay already climbs on its own, so scaling it further only pushed clients toward the ceiling sooner without spreading them any better. 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#278599 Forward-Port-Of: odoo/odoo#276869
20 changes
Enhancements to existing features
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278805 Forward-Port-Of: odoo/odoo#278208
Original PR description
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278805 Forward-Port-Of: odoo/odoo#278208
Resolved issues and error corrections
Steps to reproduce: - Install the `l10n_br` module. - Go to Portal > Addresses > Add Address > select Brazil as the country. (Do not change the company's country to Brazil) Issue: - The address layout is broken: the Street input has no label and `Steet and Number` field is missing. Cause: - The `o_extended_address` elements are not rendered when the company country is not Brazil. When the user selects Brazil, `_setVisibility` looks for `o_extended_address` elements but finds none, s
Original PR description
Steps to reproduce: - Install the `l10n_br` module. - Go to Portal > Addresses > Add Address > select Brazil as the country. (Do not change the company's country to Brazil) Issue: - The address layout is broken: the Street input has no label and `Steet and Number` field is missing. Cause: - The `o_extended_address` elements are not rendered when the company country is not Brazil. When the user selects Brazil, `_setVisibility` looks for `o_extended_address` elements but finds none, so it fails to make the standard address fields visible. Fix: - Restore the company country condition in JS so `o_standard_address` is not hidden when no `o_extended_address` elements are rendered. Forward-Port-Of: odoo/odoo#278008
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 Forward-Port-Of: odoo/odoo#278895
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 Forward-Port-Of: odoo/odoo#278895
Description of the issue/feature this PR addresses: Updates `test_auth_ldap` to retrieve the company associated with the current environment instead of relying on a hardcoded value. This prevents test failures in environments where the hardcoded company does not exist. Resolves https://runbot.odoo.com/odoo/error/243763 opw-6353706
Original PR description
Description of the issue/feature this PR addresses: Updates `test_auth_ldap` to retrieve the company associated with the current environment instead of relying on a hardcoded value. This prevents test failures in environments where the hardcoded company does not exist. Resolves https://runbot.odoo.com/odoo/error/243763 opw-6353706
## Issue In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager. ## Steps to reproduce 1. Install *Attendances* (`hr_attendance`) 2. In Settings: - Toggle *Attendances from Backend* - Toggle *Absence Management* - Toggle *Display Extra Hours* - Set *Extra Hours Validation* to *Approved by Manager* 3. On an Employee E: - Overtime Ruleset: Default Ruleset 4. In Attendances, create an attendance for emplo
Original PR description
## Issue In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager. ## Steps to reproduce 1. Install *Attendances* (`hr_attendance`) 2. In…
## Issue
In Attendances > Management, negative overtimes do not appear in the list, even if they need approval from a manager.
## Steps to reproduce
1. Install *Attendances* (`hr_attendance`)
2. In Settings:
- Toggle *Attendances from Backend*
- Toggle *Absence Management*
- Toggle *Display Extra Hours*
- Set *Extra Hours Validation* to *Approved by Manager*
3. On an Employee E:
- Overtime Ruleset: Default Ruleset
4. In Attendances, create an attendance for employee E on a day where they are expected to work. The attendance should be shorter than a full day of work (e.g., from 9:00am to 11:00am, which would be -6 hours of overtime if 8 hors are expected).
5. Navigate to Attendances > Management
6. **The attendance created in Step 4 does not appear, even though it should be approved by a manager.**
## Cause
The domain for the `hr_attendance_management_action` is the following:
https://github.com/odoo/odoo/blob/22a94663e4c1672366b7a614943cef843ced3503/addons/hr_attendance/views/hr_attendance_view.xml#L439
The `overtime_hours > 0` condition was added by https://github.com/odoo/odoo/commit/e5067262174725466056e9a6c530439b4845c19b with the intent to remove attendance records with zero extra hours. Instead, it removes all records with less than zero extra hours.
opw-6372360**Steps to reproduce:** 1. Enable "Display Product Images" in Sales settings 2. Set the document layout table style to Boxed, Bubble or Column [Settings -> Companies -> Document Layout] 3. Create a quotation with a product that has an image and a long description 4. Print the quotation as PDF **Issue:** The product description text overflows the Description column boundary and crosses into the Quantity column, overlapping the separator line **Why this happens:** - The `td_product_nam
Original PR description
**Steps to reproduce:** 1. Enable "Display Product Images" in Sales settings 2. Set the document layout table style to Boxed, Bubble or Column [Settings -> Companies -> Document Layout] 3. Create a quotation with a product that has an image and a long description 4. Print the quotation as PDF **Issue:** The product description text overflows the Description column boundary and crosses into the Quantity column, overlapping the separator line **Why this happens:** - The `td_product_name` cell uses a `d-flex` container to place the product image and description text side by side - wkhtmltopdf does not properly constraint the text div's width, so it's width grew wider than the `td` **Fix:** - Replace the `d-flex` wrapper with a CSS `float` layout - `overflow: hidden` on `.o_product_name_cell` prevents overlap on sibling float and automatically occupy exactly the remaining width beside it opw-6408701
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for Lot/Serial in the notification systray should apply the Late activities filter. ## Steps to reproduce: 1. Install Inventory (stock) module, make sure to enable Lots & Serial Numbers in Inventory > Traceability 2. Create some new Lots / Serial numbers 3. Add some Activities with Due Date before to
Original PR description
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for…
## Current behavior: Clicking on the Late activity for Lot/Serial in the notification systray doesn't apply the Late activities filter. ## Expected behavior: Clicking on the Late activity for Lot/Serial in the notification systray should apply the Late activities filter. ## Steps to reproduce: 1. Install Inventory (stock) module, make sure to enable Lots & Serial Numbers in Inventory > Traceability 2. Create some new Lots / Serial numbers 3. Add some Activities with Due Date before today 4. Observe that the Clock icon on systray will count up, showing the number of activities that are late, for today and for future 5. Click on the Late activities (e.g. 2 Late) should only show the 2 late activities. Instead, no filter is applied, thus showing all the Lots / Serial numbers in the inventory ## Cause of the issue: Missing filters for Late, Today and Future activities in the stock_lot_views.xml ## Fix: Added 3 filters for Late, Today and Future activities opw-6332560 Forward-Port-Of: odoo/odoo#278165 Forward-Port-Of: odoo/odoo#272735
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
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the return
Original PR description
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem:…
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the returned combination was correct. The 0.5s threshold is an arbitrary sanity check meant to catch a gross algorithmic regression (e.g. loss of early pruning of invalid combinations), not a strict performance SLA, so it is too tight to survive normal CI load variance. Solution: Raise the threshold to 2 seconds, keeping enough margin to absorb CI load variance while still catching a real performance regression, which would take far longer than the current computation. runbot-243606 Forward-Port-Of: odoo/odoo#277986
Steps to reproduce the bug: - Create a purchase requisition: - add any storable product and vendor - From it, create a purchase order and confirm it -> a picking is created - Cancel the "purchase.requisition" Problem: The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it. In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs,
Original PR description
Steps to reproduce the bug:
- Create a purchase requisition:
- add any storable product and vendor
- From it, create a purchase order and confirm it -> a picking is created
- Cancel the "purchase.requisition"
Problem:
The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it.
In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs, with no check on their current state or on whether picking or invoices existed.
Solution:
Only cancel linked purchase orders that are still in 'draft' state. Once
outside of that state, the purchase process might be too far engaged to
simply cancel the purchase order without notice.
opw-6329742
Forward-Port-Of: odoo/odoo#272190Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: . Add safe execution to the element before use focus() task-6409715 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278083
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: . Add safe execution to the element before use focus() task-6409715 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278083
Currently, an error occurs when grouping invoice lines by tax. **Steps to Reproduce:** - Install the `Accounting` module. - Go to `Accounting` > `Customers` > `Invoices` and `create an invoice`. - Add an `invoice line`, set a `price`, and select an `account`. - Go to `Accounting` > `Configuration` > `Chart of Accounts`, open the account used on the invoice line, and clear its `Code` field. - Return to the `invoice`, click `Action` > `(Un)Group lines by tax`. `ValueError: Typ
Original PR description
Currently, an error occurs when grouping invoice lines by tax. **Steps to Reproduce:** - Install the `Accounting` module. - Go to `Accounting` > `Customers` > `Invoices` and `create an invoice`. -…
Currently, an error occurs when grouping invoice lines by tax.
**Steps to Reproduce:**
- Install the `Accounting` module.
- Go to `Accounting` > `Customers` > `Invoices` and `create an invoice`.
- Add an `invoice line`, set a `price`, and select an `account`.
- Go to `Accounting` > `Configuration` > `Chart of Accounts`, open the account used on
the invoice line, and clear its `Code` field.
- Return to the `invoice`, click `Action` > `(Un)Group lines by tax`.
`ValueError: TypeError('sequence item 1: expected str instance, bool found') while evaluating`
`'if records:\n records.action_group_ungroup_lines_by_tax()'`
After this [recent commit], account codes became optional and can be removed. As a result,
when a user adds an account with no code to an invoice line and groups the lines by the same
tax, it creates the grouped line from here [1]. Then, when it gets the account code from the
grouped line to prepare the name, the code is False, which raises the error [2].
This commit ensures that the grouped line name is built using filter(None, ...), which removes
None and other falsy values, so that the account code is included if it exists; otherwise,
it is not included.
[recent commit]: https://github.com/odoo/odoo/commit/c3313b336b9f1305c363097745926f2bdf61e277
[1]- https://github.com/odoo/odoo/blob/92ced215895d027a2b5606dbecbf3eb96b9dcd10/addons/account_edi_ubl_cii/models/account_move.py#L156-L158
[2]- https://github.com/odoo/odoo/blob/92ced215895d027a2b5606dbecbf3eb96b9dcd10/addons/account_edi_ubl_cii/models/account_move.py#L189-L193
sentry-7598941609
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prBefore this commit, starting a tour in test mode on the tours viewz wasn't triggering the redirect at the first step of the tour. Now, it redirect. TASK-6331071 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
Before this commit, starting a tour in test mode on the tours viewz wasn't triggering the redirect at the first step of the tour. Now, it redirect. TASK-6331071 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The implementation of the highlight of missing required settings (#249321) was discarding the `SearchableSetting` if the `<setting>` had no `id`. This behavior disabled the highlight of the setting formPage in those cases. This commit fixes the issue by allowing `settingId` to be undefined. Note that `settingId` can safely be undefined since it is used only for the highlight behavior and during a case of url hash check. task-6364849
Original PR description
The implementation of the highlight of missing required settings (#249321) was discarding the `SearchableSetting` if the `<setting>` had no `id`. This behavior disabled the highlight of the setting formPage in those cases. This commit fixes the issue by allowing `settingId` to be undefined. Note that `settingId` can safely be undefined since it is used only for the highlight behavior and during a case of url hash check. task-6364849
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
Original PR description
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial Numbers on Invoices" - Create a product tracked by serial/lot and enable the dropship route - Create two lots: "lot1" and "lot2" - Create and confirm a SO for quantity 2 - Confirm the PO and validate the dropship for both lots - Create and post an invoice - Return "lot2" from the dropship pick
Original PR description
**Issue** Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report. **Steps to reproduce** - Activate "Display Lots & Serial…
**Issue**
Printing an invoice for a returned dropshipped tracked product could display the wrong lot/serial number on the invoice report.
**Steps to reproduce**
- Activate "Display Lots & Serial Numbers on Invoices"
- Create a product tracked by serial/lot and enable the dropship route
- Create two lots: "lot1" and "lot2"
- Create and confirm a SO for quantity 2
- Confirm the PO and validate the dropship for both lots
- Create and post an invoice
- Return "lot2" from the dropship picking
- Create and post a credit note for quantity 1
- Click on print on the invoice
-> The generated PDF displays "lot1 & lot2" instead of "lot1"
**Cause**
While rendering `account.report_invoice_with_payments`, the report calls `_get_invoiced_lot_values` to determine which lot/serial numbers should be displayed:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L31-L32 `invoiced_qties = 2` since the invoice is on a quantity of 2 https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L44 Three stock move lines are retrieved from the SO:
- the two original dropship deliveries,
- the return move for `lot2`. https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L63 However, none of them are considered as `is_stock_return` because the dropship locations use `supplier` instead of `internal`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L72-L76 As a consequence:
- The two original delivery move lines each keep quantity `1`: https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L69 they never pass through the return handling logic (as they should be): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L77-L80
- for the last one, `is_stock_return = False` while it should not, thus the quantity is 1 instead of 0. Furthermore, it does not pass by this code:
https://github.com/odoo/odoo/blob/8759429547e42e9f63b15a7c80475be46ef437e2/addons/sale_stock/models/account_move.py#L79 which would make the quantity for lot2 equalled to 0 (1-1) The quantities are therefore accumulated as:
https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L92
resulting in:
`qties_per_lot = {lot1: 1, lot2: 2}`
instead of:
`qties_per_lot = {lot1: 1, lot2: 0}`
The report selects both lots since it starts with lot1 (qty of 1): https://github.com/odoo/odoo/blob/786c373d5ac8afdfb79eb7a7d69c5eb83b919625/addons/sale_stock/models/account_move.py#L94-L99
opw-6236855
Forward-Port-Of: odoo/odoo#270599This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
Original PR description
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
Miscellaneous changes
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the m
Original PR description
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a…
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the many clients fan out over a much wider window and the registry recomputes spread over time instead of colliding. Raise the ceiling on the retry delay to two minutes to match that wider spread, and drop the exponential growth factor: with a thirty-second jitter accumulating on every attempt, the delay already climbs on its own, so scaling it further only pushed clients toward the ceiling sooner without spreading them any better. 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#278599 Forward-Port-Of: odoo/odoo#276869
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#278690 Forward-Port-Of: odoo/odoo#266108
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA
Original PR description
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278542
19 changes
Enhancements to existing features
This PR adapts the update dialog to fit the new update logic which is individual to every iot box related PR: https://github.com/odoo/odoo/pull/278661
Original PR description
This PR adapts the update dialog to fit the new update logic which is individual to every iot box related PR: https://github.com/odoo/odoo/pull/278661
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278805 Forward-Port-Of: odoo/odoo#278208
Original PR description
Give clearer, more accurately attributed error messages, and add validation to catch classification code / General Public TIN mismatches before they reach MyInvois. task-4651934 Forward-Port-Of: odoo/odoo#278805 Forward-Port-Of: odoo/odoo#278208
Resolved issues and error corrections
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 Forward-Port-Of: odoo/odoo#278895
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 Forward-Port-Of: odoo/odoo#278895
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the return
Original PR description
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem:…
Steps to reproduce the bug: - Run the product module test suite on a loaded/slow CI runner - Observe test_get_first_possible_combination occasionally failing Problem: test_get_first_possible_combination asserts that _get_first_possible_combination() completes in under 0.5 seconds on a template with 10 attributes x 50 values and exclusion rules. On a busy runner (Testing country uk build) it took 0.587s and the test failed with `0.5868358612060547 not less than 0.5`, even though the returned combination was correct. The 0.5s threshold is an arbitrary sanity check meant to catch a gross algorithmic regression (e.g. loss of early pruning of invalid combinations), not a strict performance SLA, so it is too tight to survive normal CI load variance. Solution: Raise the threshold to 2 seconds, keeping enough margin to absorb CI load variance while still catching a real performance regression, which would take far longer than the current computation. runbot-243606 Forward-Port-Of: odoo/odoo#277986
Steps to reproduce the bug: - Create a purchase requisition: - add any storable product and vendor - From it, create a purchase order and confirm it -> a picking is created - Cancel the "purchase.requisition" Problem: The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it. In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs,
Original PR description
Steps to reproduce the bug:
- Create a purchase requisition:
- add any storable product and vendor
- From it, create a purchase order and confirm it -> a picking is created
- Cancel the "purchase.requisition"
Problem:
The confirmed purchase order was cancelled even though it had already been validated (state = 'purchase') and had active receipts or vendor bills attached to it.
In `action_cancel`, `requisition.purchase_ids.button_cancel()` is called unconditionally on all linked POs, with no check on their current state or on whether picking or invoices existed.
Solution:
Only cancel linked purchase orders that are still in 'draft' state. Once
outside of that state, the purchase process might be too far engaged to
simply cancel the purchase order without notice.
opw-6329742
Forward-Port-Of: odoo/odoo#272190[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 - Select US jobs and search for the remote job. 4 - All countries filter is readonly and it is not pressable. Bug cause: 1 - Check is done with jobs value 1.1 - If no matching, readonly button is displayed. Bug solution: 1 - count_per_filter is used instead of
Original PR description
[FIX] website_hr_recruitment: fix country filter Bug reproduction: 1 - Recruitment, you need to have 1 remote and 1 US jobs at least. 2 - Go to job page in website, activate country filter. 3 -…
[FIX] website_hr_recruitment: fix country filter
Bug reproduction:
1 - Recruitment, you need to have 1 remote and 1 US jobs at least.
2 - Go to job page in website, activate country filter.
3 - Select US jobs and search for the remote job.
4 - All countries filter is readonly and it is not pressable.
Bug cause:
1 - Check is done with jobs value
1.1 - If no matching, readonly button is displayed.
Bug solution:
1 - count_per_filter is used instead of jobs
1.1 - Even there are matchings for other countries, it shows.
2 - Also, searched keyword is added to filter url
2.1 - When there is search in other country and we click to it:
2.2 - The searched keyword will be still there.
task-6284436
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#277726The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
Original PR description
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
Original PR description
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition. - Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position. runbot-error: 941390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-P
Original PR description
- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition.
- Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position.
runbot-error: 941390
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278813The bugfix introduced in https://github.com/odoo/odoo/commit/01d11a770f89c391f7c6a2c46a3d770d10afb428 made it so that "personal" outgoing mail servers are blocked/ignored from being used in email marketing as dedicated servers. In doing so, it missed the fact that while in *Email Marketing > Settings*, the "Dedicated Server" picker now correctly ignores personal OMS entries, the selection widget for `mail_server_id` in `view_mail_mass_mailing_form` still let's you manually select a OMS with a
Original PR description
The bugfix introduced in https://github.com/odoo/odoo/commit/01d11a770f89c391f7c6a2c46a3d770d10afb428 made it so that "personal" outgoing mail servers are blocked/ignored from being used in email…
The bugfix introduced in https://github.com/odoo/odoo/commit/01d11a770f89c391f7c6a2c46a3d770d10afb428 made it so that "personal" outgoing mail servers are blocked/ignored from being used in email marketing as dedicated servers.
In doing so, it missed the fact that while in *Email Marketing > Settings*, the "Dedicated Server" picker now correctly ignores personal OMS entries, the selection widget for `mail_server_id` in `view_mail_mass_mailing_form` still let's you manually select a OMS with an owner set. As there is not warning or an explicit error, this can lead to accidental miss configurations on an email marketing campaign, where the selected OMS will be actually ignored by the backend.
To align the changes introduced by the bugfix, we add a search domain to the selection field, so that only OMS with `('owner_user_id', '=', False)` will be presented as a choice.
OPW-6388562
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278595# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in one language (Should be something like /shop/category/name-x) - Have two websites, each with a different default language - Create a link to the shop category in each website. > ! The link must be the exact same > You can put it in the header menu for simplicity - Open the website editor - D
Original PR description
# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in…
# How to reproduce
- Have two language in the db
- Create an e-Commerce category
- Have a different translation for each language for that category's name
- Copy the link to that category's name in one language (Should be something like /shop/category/name-x)
- Have two websites, each with a different default language
- Create a link to the shop category in each website.
> ! The link must be the exact same
> You can put it in the header menu for simplicity
- Open the website editor
- Do 2 or 3 times :
- click on the category link and switch website
# The issue
A traceback is displayed
# Cause
This manipulation will make us enter an infinite redirect scenario described here :
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/website/static/src/client_actions/website_preview/website_builder_action.js#L371-L384
The problem is that this commit introduced an assignation to `iframe.contentDocument.body` before the patch :
https://github.com/odoo/odoo/commit/89994eb7a54ca606bab26b6d579d03e86c11ba60
But in our case, iframe.contentDocument is null, so it throws an error before the patch can be applied
opw-6322115
Forward-Port-Of: odoo/odoo#276634Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrol
Original PR description
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist"…
Steps to reproduce the issue easily: - Remove the section in the footer. - Drop enough snippets to have a scroll bar and to not see the footer when the scroll is at the top. - Drop the "Pricelist" snippet at the bottom of the page and click on a column. - Scroll up so the footer and the bottom of the snippet are not visible, and add a pricelist item with the "Add Product" option. - => The page scrolls to the new item, but a big white space appears at the bottom of the screen, as if we scrolled too far. The same issue happens with similar steps in the following cases: - When using any option using the `addItem` action. - When undoing/redoing a step that was done in an element not in the viewport (the screen will scroll to it and we will have the issue). - When showing an invisible element (the screen will scroll to it if not in the viewport) - Adding a grid item with the "Add Elements" option. - Adding a new card in the "Floating Cards" snippet. The common point to all these cases is that they all scroll to the added or shown element with the `scrollIntoView` built-in function, which scrolls everything, including the viewport. It also doesn't take into account the header that changes during the scroll, often ending with the element hidden by the header. This commit fixes these issues by using the builder `scrollTo` util, which takes the header into account and only scrolls what needs to be. This function should always be preferred when scrolling in the builder. task-6314322 Forward-Port-Of: odoo/odoo#277865 Forward-Port-Of: odoo/odoo#275686
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a trailing parasitic digit (such as 53000.0000000002 instead of 53000.0000000000). This commit resolves the issue by backporting the formatting logic from master. The `maxDecDigits` calculation is moved outside the conditionals so it unconditionally caps precision for all numbers. Furthermore, the
Original PR description
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a…
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a trailing parasitic digit (such as 53000.0000000002 instead of 53000.0000000000). This commit resolves the issue by backporting the formatting logic from master. The `maxDecDigits` calculation is moved outside the conditionals so it unconditionally caps precision for all numbers. Furthermore, the global significant digit ceiling is reduced from 15 to 14. This 14-digit ceiling reserves a 1-digit buffer, allowing the newly introduced `formatFixedDecimals` utility to safely run `roundDecimals` on the float. This mathematically sanitizes the trailing corrupted digit before it is ever converted to a string. opw-6313540 **Current behavior before PR:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed with a corrupted digit (e.g. 53000.0000000002) **Desired behavior after PR is merged:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed without corrupted digits (e.g. 53000.000000000) This PR is essentially a backport of https://github.com/odoo/odoo/commit/07da917f6e3319b4acde1029e77f69f1aba314b8 and https://github.com/odoo/odoo/commit/c4e7ba8d8fdfd7b0c442cf834f562ef8cedf019b for numbers.js Forward-Port-Of: odoo/odoo#277898 Forward-Port-Of: odoo/odoo#272940
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_tax_luxury_sales ``` Reason-1 : - In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were ad
Original PR description
Error-1 : ``` raise ValueError('External ID not found in the system: %s' % xmlid) ValueError: External ID not found in the system: account.1_l10n_id_domestic_fiscal_position ``` Error-2 : ``` raise…
Error-1 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system:
account.1_l10n_id_domestic_fiscal_position
```
Error-2 :
```
raise ValueError('External ID not found in the system: %s' % xmlid)
ValueError: External ID not found in the system: account.1_tax_luxury_sales
```
Reason-1 :
- In [this](https://github.com/odoo/odoo/commit/e342a45aceb60b44052c5d52e9ecc35a9a7340da) commit new account.fiscal.positions were added and linked to acc.tax using fiscal_position_ids .
- In [this](https://github.com/odoo/odoo/blob/saas-19.2/addons/l10n_id/migrations/1.3/end-migrate_update_taxes.py) migration script, while creating taxes it didnt find fiscal positions, so need to create them first.
Reason-2 :
- original_tax_ids was also added in same commit, if client deleted those tax(ie tax_luxury_sales) will fail while creating `tax_luxury_sales_pemungut_ppn`, It needs to be created first too.
- upg : [4341887](https://upgrade.odoo.com/odoo/upgrade.request/4341887)
- opw : [6285978](https://www.odoo.com/odoo/project/70/tasks/6285978)
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-prSince a cron can be manually or automatically disabled, it is interesting to track when and by who a cron a disabled or re-enabled. So we just add tracking on the active field. 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
Original PR description
Since a cron can be manually or automatically disabled, it is interesting to track when and by who a cron a disabled or re-enabled. So we just add tracking on the active field. 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
Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an AccessError is thrown. Invoicing group members should be able to handle payments so this is an issue. --- Steps to reproduce: 1. Make sure sale_management and l10n_pl_bank_verification are installed. 2. Create a new user with "Invoicing" Accounting group. 3. Create a new sales order with sai
Original PR description
Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an…
Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an AccessError is thrown. Invoicing group members should be able to handle payments so this is an issue. --- Steps to reproduce: 1. Make sure sale_management and l10n_pl_bank_verification are installed. 2. Create a new user with "Invoicing" Accounting group. 3. Create a new sales order with said user (any customer, any product) 4. Confirm the quotations and, from its form view, "Create Invoice". 5. Confirm the invoice and, from its form view, "Pay". 6. Upon clicking "Create Payment", an Access Error is thrown. --- Desired behavior after this commit is merged: This commit makes sure an Invoicing group member is able to create the payment withtout AccessErrors being thrown. --- task-none feedback from: https://github.com/odoo/odoo/pull/267992 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278688 Forward-Port-Of: odoo/odoo#270008
Miscellaneous changes
### before ~1.4s <img width="1869" height="819" alt="image" src="https://github.com/user-attachments/assets/168e3831-929b-43fd-9aa1-ea5bfb22d3fe" /> ### after ~570ms <img width="1862" height="860" alt="image" src="https://github.com/user-attachments/assets/ea907064-fe12-4711-9707-67926f05cedf" /> See commit messages --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
### before ~1.4s <img width="1869" height="819" alt="image" src="https://github.com/user-attachments/assets/168e3831-929b-43fd-9aa1-ea5bfb22d3fe" /> ### after ~570ms <img width="1862" height="860" alt="image" src="https://github.com/user-attachments/assets/ea907064-fe12-4711-9707-67926f05cedf" /> See commit messages --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the m
Original PR description
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a…
When a bus process restarts, every client on every database it serves loses its websocket at the same instant and immediately schedules a reconnection. Each database that comes back triggers a registry recompute server-side, so a tight reconnection window makes all of those recomputes land together and pile up on the freshly started process. The jitter added to each reconnection delay was only one second, far too narrow to break up that wave. Widen it to thirty seconds so the retries of the many clients fan out over a much wider window and the registry recomputes spread over time instead of colliding. Raise the ceiling on the retry delay to two minutes to match that wider spread, and drop the exponential growth factor: with a thirty-second jitter accumulating on every attempt, the delay already climbs on its own, so scaling it further only pushed clients toward the ceiling sooner without spreading them any better. 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#278599 Forward-Port-Of: odoo/odoo#276869
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA
Original PR description
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278542
17 changes
Enhancements to existing features
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag an
Original PR description
Previously, questions in the event template could not be reordered via drag-and-drop on the Questions page. Instead of adding the handle to the inline list embedded in the event.type form view, we add it to the dedicated event.question list view (event_question_view_list). This will allow the users to reorder from the event questions and the sequence will be synced everywhere those questions appear. Steps to reproduce: 1.Go to event, configurations, and event questions. 2.We can't drag and drop questions Original PR (18.0): odoo/odoo#270576 opw-6260478
Resolved issues and error corrections
### Issue: The fix in commit `f0d164d3ab` introduced one cash rounding record per Indian company for new installations, but existing databases were not updated Indian companies created before that fix still share the old `l10n_in.cash_rounding_in_half_up` record, and moves may be linked to a cash rounding belonging to another company ### Cause: No migration script was included with the original fix The script creates a dedicated cash rounding record for each Indian company that does n
Original PR description
### Issue: The fix in commit `f0d164d3ab` introduced one cash rounding record per Indian company for new installations, but existing databases were not updated Indian companies created before that…
### Issue: The fix in commit `f0d164d3ab` introduced one cash rounding record per Indian company for new installations, but existing databases were not updated Indian companies created before that fix still share the old `l10n_in.cash_rounding_in_half_up` record, and moves may be linked to a cash rounding belonging to another company ### Cause: No migration script was included with the original fix The script creates a dedicated cash rounding record for each Indian company that does not already have one, reassigns existing moves to the correct record, and migrates the XML ID of the original shared record to the new per-company format ### Steps to reproduce: - Create a database with `l10n_in` installed before commit `f0d164d3ab` - Create an invoice and set its Cash Rounding to `Half Up` - Create a new Indian company (the `Half Up` record is now reassigned to the new company) - Repeat the previous two steps as many times as desired - Apply the fix (without the migration script) and upgrade `l10n_in` Before the fix, invoices from other companies still reference the shared cash rounding record belonging to the last created company - Apply the migration script and upgrade again After the fix, each company has its own cash rounding record and existing invoices are reassigned correctly opw-6318857
Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record. - Delete its `linked overtime rules`. - Install the `hr_holidays_attendance` module. **Error:** ```py Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule' odoo.tools.conver
Original PR description
Currently, an error occurs when installing the hr_holidays_attendance module. **Steps to Reproduce:** - Install the `hr_attendance` module without demo data. - Go to `Attendance` > `Configuration` >…
Currently, an error occurs when installing the hr_holidays_attendance module.
**Steps to Reproduce:**
- Install the `hr_attendance` module without demo data.
- Go to `Attendance` > `Configuration` > `Overtime Rulesets` and open the `Default Ruleset` record.
- Delete its `linked overtime rules`.
- Install the `hr_holidays_attendance` module.
**Error:**
```py
Exception: Cannot update missing record 'hr_attendance.hr_attendance_overtime_employee_schedule_rule'
odoo.tools.convert.ParseError: while parsing /home/odoo/odoo18/community/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml:7, somewhere inside <record id="hr_attendance.hr_attendance_overtime_employee_schedule_rule" model="hr.attendance.overtime.rule">
<field name="compensable_as_leave" eval="True"/>
</record>
```
This error occurs when the user deletes all overtime rules and then installs the hr_holidays_attendance
module. During installation, the module attempts to update the deleted overtime rule records,
which raises an error [1].
This commit uses forcecreate="0" to skip updating records if the corresponding overtime
rules do not exist.
[1]- https://github.com/odoo/odoo/blob/da0a83761f38ee4a2940015b6c8f7190c310a4a0/addons/hr_holidays_attendance/data/hr_holidays_attendance_data.xml#L7-L12
sentry-7372074675
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition. - Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position. runbot-error: 941390 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-P
Original PR description
- Fix: The edit() calls now pass { confirm: false } to avoid calling the extra step that involved clicking manually on the input to trigger the search and the dropdown display. This should remove the race condition.
- Small cleanup: clickFieldDropdownItem replaces the hardcoded ".dropdown-item:nth-child(1)" click, allowing selecting by product name instead of position.
runbot-error: 941390
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278813When `cash_rounding` is enabled on a POS config but `rounding_method` is not set,`get_tax_totals_summary` is called with undefined (instead of null). Fix: ensure the `rounding_method` is set when `cash_rounding` is enabled, otherwise pass null to `get_tax_totals_summary`. task-id: 6388234 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276914
Original PR description
When `cash_rounding` is enabled on a POS config but `rounding_method` is not set,`get_tax_totals_summary` is called with undefined (instead of null). Fix: ensure the `rounding_method` is set when `cash_rounding` is enabled, otherwise pass null to `get_tax_totals_summary`. task-id: 6388234 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#276914
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a trailing parasitic digit (such as 53000.0000000002 instead of 53000.0000000000). This commit resolves the issue by backporting the formatting logic from master. The `maxDecDigits` calculation is moved outside the conditionals so it unconditionally caps precision for all numbers. Furthermore, the
Original PR description
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a…
**Description of the issue/feature this PR addresses:** When rendering floating-point numbers with high decimal accuracy (e.g., UoM quantities set to 10 decimals), the UI can occasionally display a trailing parasitic digit (such as 53000.0000000002 instead of 53000.0000000000). This commit resolves the issue by backporting the formatting logic from master. The `maxDecDigits` calculation is moved outside the conditionals so it unconditionally caps precision for all numbers. Furthermore, the global significant digit ceiling is reduced from 15 to 14. This 14-digit ceiling reserves a 1-digit buffer, allowing the newly introduced `formatFixedDecimals` utility to safely run `roundDecimals` on the float. This mathematically sanitizes the trailing corrupted digit before it is ever converted to a string. opw-6313540 **Current behavior before PR:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed with a corrupted digit (e.g. 53000.0000000002) **Desired behavior after PR is merged:** - With Product UoM set to 10 Decimal Accuracy, floats such as 53000 are displayed without corrupted digits (e.g. 53000.000000000) This PR is essentially a backport of https://github.com/odoo/odoo/commit/07da917f6e3319b4acde1029e77f69f1aba314b8 and https://github.com/odoo/odoo/commit/c4e7ba8d8fdfd7b0c442cf834f562ef8cedf019b for numbers.js Forward-Port-Of: odoo/odoo#276406 Forward-Port-Of: odoo/odoo#272940
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5 karma (to give him enough rights to answer and comment) - Connect with the portal user and go to the post - Create an answer - Try to comment on your own answer - AccessError is raised **Issue:** Since [1] we check comodel access (in this case `res.partner`) when adding records. Here
Original PR description
**Steps to reproduce:** - Install website_forum - Create a new post on the forum with the admin - Subscribe to the post notifications using the bell button - Create a new portal user and give him 5…
**Steps to reproduce:**
- Install website_forum
- Create a new post on the forum with the admin
- Subscribe to the post notifications using the bell button
- Create a new portal user and give him 5 karma
(to give him enough rights to answer and comment)
- Connect with the portal user and go to the post
- Create an answer
- Try to comment on your own answer
- AccessError is raised
**Issue:**
Since [1] we check comodel access (in this case `res.partner`) when adding records. Here during the `message_post` the `question_followers` are added manually as `partner_ids` before sending (the logic only relies on the original post subscribers, not on the added comment/reply).
```py
question_followers = self.env['mail.followers'].sudo().search([
('res_model', '=', self._name),
('res_id', '=', self.parent_id.id),
('partner_id', '!=', False),
]).filtered(lambda fol: comment_subtype in fol.subtype_ids).mapped('partner_id')
partner_ids += question_followers.ids
```
As the portal user has no `read` access to the subscribers the message creation fails with a traceback.
**Fix:**
Add `sudo` to the `message_post` call of `post_comment`.
(Also fix a minor display issue in the 'Karma Error' notification)
[1] https://github.com/odoo/odoo/commit/aae732957c3c3b3590f5686cfccc0ab264d0b5c9
opw-5318757
Forward-Port-Of: odoo/odoo#274751The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
Original PR description
The test that verifies the behavior of cancelling the link popover during an attachment upload relies on a hard-coded delay. Occasionally, when the test runs on an overloaded runbot infrastructure, the upload manages to complete before the discard happens. This commit fixes this by making sure the upload never completes within the test. runbot-940190 runbot-944098 Forward-Port-Of: odoo/odoo#278820
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
Original PR description
This commit [1] added a top margin to headings for the html_editor. However, this margin was also applied in the website, breaking the WYSIWYG behavior. Exclude the website from this rule so the margin is only applied in the html_editor. [1]: https://github.com/odoo/odoo/commit/13a452106733c950a7e25cfeb5107eb03367b756 Forward-Port-Of: odoo/odoo#278730
To improve compliance with French requirements for FEC exports. Now we avoid exporting empty or placeholder labels ('/') by improving the fallback logic for EcritureLib. So now we, - Use existing line label when valid - For receivable/payable lines, fallback to 'partner - reference' - Otherwise fallback to move reference or name - Replace '/' with 'Balance initiale' for opening entries Related: https://github.com/odoo/enterprise/pull/112822 task-5346068 Forward-Port-Of: odoo/odoo#2572
Original PR description
To improve compliance with French requirements for FEC exports. Now we avoid exporting empty or placeholder labels ('/') by improving the fallback logic for EcritureLib. So now we,
- Use existing line label when valid
- For receivable/payable lines, fallback to 'partner - reference'
- Otherwise fallback to move reference or name
- Replace '/' with 'Balance initiale' for opening entries
Related: https://github.com/odoo/enterprise/pull/112822
task-5346068
Forward-Port-Of: odoo/odoo#257242Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an AccessError is thrown. Invoicing group members should be able to handle payments so this is an issue. --- Steps to reproduce: 1. Make sure sale_management and l10n_pl_bank_verification are installed. 2. Create a new user with "Invoicing" Accounting group. 3. Create a new sales order with sai
Original PR description
Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an…
Description of the issue this commit addresses: When a member of the Invoicing group tries to create a payment trough the L10nPlAccountPaymentRegister wizard, upon clicking "Create Payment", an AccessError is thrown. Invoicing group members should be able to handle payments so this is an issue. --- Steps to reproduce: 1. Make sure sale_management and l10n_pl_bank_verification are installed. 2. Create a new user with "Invoicing" Accounting group. 3. Create a new sales order with said user (any customer, any product) 4. Confirm the quotations and, from its form view, "Create Invoice". 5. Confirm the invoice and, from its form view, "Pay". 6. Upon clicking "Create Payment", an Access Error is thrown. --- Desired behavior after this commit is merged: This commit makes sure an Invoicing group member is able to create the payment withtout AccessErrors being thrown. --- task-none feedback from: https://github.com/odoo/odoo/pull/267992 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278688 Forward-Port-Of: odoo/odoo#270008
**Issue** A traceback is raised when creating a batch if the batch sequence prefix does not contain the expected '/' separator. **Steps to reproduce** - Go to settings > technical > sequences & identifiers > sequence: - batch transfer: - prefix: BATCH- - Create a new batch: - operation type: delivery orders - Try to save -> a traceback is triggered: ```ValueError: not enough values to unpack (expected 2, got 1)``` **Cause** `_prepare_name()` assumes that the sequence
Original PR description
**Issue**
A traceback is raised when creating a batch if the batch sequence prefix does not contain the expected '/' separator.
**Steps to reproduce**
- Go to settings > technical > sequences & identifiers > sequence:
- batch transfer: - prefix: BATCH-
- Create a new batch:
- operation type: delivery orders
- Try to save -> a traceback is triggered:
```ValueError: not enough values to unpack (expected 2, got 1)```
**Cause**
`_prepare_name()` assumes that the sequence returned by
`next_by_code()` contains a '/' separator and directly unpacks the
result of `rsplit('/', 1)`.
When no '/' is present, `rsplit()` returns a list containing a single
element, causing the unpacking to fail.
https://github.com/odoo/odoo/blob/18407651d2912b7d30463ec72cd379177530ef4f/addons/stock_picking_batch/models/stock_picking_batch.py#L418-L419
opw-6304270
Forward-Port-Of: odoo/odoo#272212# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in one language (Should be something like /shop/category/name-x) - Have two websites, each with a different default language - Create a link to the shop category in each website. > ! The link must be the exact same > You can put it in the header menu for simplicity - Open the website editor - D
Original PR description
# How to reproduce - Have two language in the db - Create an e-Commerce category - Have a different translation for each language for that category's name - Copy the link to that category's name in…
# How to reproduce
- Have two language in the db
- Create an e-Commerce category
- Have a different translation for each language for that category's name
- Copy the link to that category's name in one language (Should be something like /shop/category/name-x)
- Have two websites, each with a different default language
- Create a link to the shop category in each website.
> ! The link must be the exact same
> You can put it in the header menu for simplicity
- Open the website editor
- Do 2 or 3 times :
- click on the category link and switch website
# The issue
A traceback is displayed
# Cause
This manipulation will make us enter an infinite redirect scenario described here :
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/website/static/src/client_actions/website_preview/website_builder_action.js#L371-L384
The problem is that this commit introduced an assignation to `iframe.contentDocument.body` before the patch :
https://github.com/odoo/odoo/commit/89994eb7a54ca606bab26b6d579d03e86c11ba60
But in our case, iframe.contentDocument is null, so it throws an error before the patch can be applied
opw-6322115
Forward-Port-Of: odoo/odoo#276634When the shop sidebar categories are enabled with collapsed categories, subcategory names could wrap unexpectedly at 100% zoom or lower, even when there was enough available space. Steps to reproduce: - Open the Shop page and click Edit - Go to the Style tab - Set Content Width to Full - Enable the Categories sidebar - Enable Collapse Category This issue caused sidebar subcategory labels to wrap only at lower zoom levels, while higher zoom levels displayed them correctly. Add CSS
Original PR description
When the shop sidebar categories are enabled with collapsed categories, subcategory names could wrap unexpectedly at 100% zoom or lower, even when there was enough available space. Steps to reproduce: - Open the Shop page and click Edit - Go to the Style tab - Set Content Width to Full - Enable the Categories sidebar - Enable Collapse Category This issue caused sidebar subcategory labels to wrap only at lower zoom levels, while higher zoom levels displayed them correctly. Add CSS rules to prevent category names in the sidebar from wrapping. opw-6296804 Forward-Port-Of: odoo/odoo#275279
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a
Original PR description
`_get_belgian_cocontractant_note()` resolves the co-contractant fiscal position through chart_template.ref(), which uses env.company. The "Send invoices automatically" cron runs as the inactive OdooBot user, so env.company is OdooBot's default company, not the invoice's. That company can differ from the invoice's and even be archived, in which case ref() raises "IndexError: tuple index out of range" (parent_ids is empty for an archived company) Steps to reproduce: - Set the main company to a non-Belgian company, and invoice from another active Belgian company. - Move every active user off the main company and archive it - Send a Belgian 0% invoice through the cron. => IndexError: tuple index out of range in chart_template.ref opw-6398778 Forward-Port-Of: odoo/odoo#278666 Forward-Port-Of: odoo/odoo#278326
When an order/invoice is fully discounted by a global discount, its base and tax amounts are sums of values each already rounded to the currency precision, so their sum is only a sub-unit floating point residue (~1e-6) instead of a clean zero. `_get_tax_totals_summary` fed that raw sum straight to the cash rounding. With a 'UP' (or 'DOWN') rounding method the residue was inflated into a full rounding step, e.g. a 0.01 total to pay on an otherwise empty document. opw-6402143 --- I confi
Original PR description
When an order/invoice is fully discounted by a global discount, its base and tax amounts are sums of values each already rounded to the currency precision, so their sum is only a sub-unit floating point residue (~1e-6) instead of a clean zero. `_get_tax_totals_summary` fed that raw sum straight to the cash rounding. With a 'UP' (or 'DOWN') rounding method the residue was inflated into a full rounding step, e.g. a 0.01 total to pay on an otherwise empty document. opw-6402143 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278291
Miscellaneous changes
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA
Original PR description
Both the `bus.bus` long-polling logic and the garbage collector vacuum cron rely on filtering by `create_date` to fetch new messages and purge expired notifications. Under heavy real-time notification usage or high client concurrency, this table grows significantly. Without an index on `create_date`, these frequent operations are forced to run full sequential scans. This commit adds a dedicated index on `create_date` to enable efficient index scans. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278542
4 changes
Resolved issues and error corrections
While fixing the conflict of #278420 I missed the percentage of the taxes and they got set as 25 and 15% instead of 0% as required in task-6254727
Original PR description
While fixing the conflict of #278420 I missed the percentage of the taxes and they got set as 25 and 15% instead of 0% as required in task-6254727
Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#277291 Forward-Port-Of: odoo/odoo#271833
Original PR description
Issue: --- Adding a rating with a message on website is causing TB as the portal user doesn't have the access to send rating message. opw-6316142 Forward-Port-Of: odoo/odoo#277291 Forward-Port-Of: odoo/odoo#271833
The mail.message/delete bus handler accessed selfMember?.seen_message_id.id with optional chaining only on selfMember, not on seen_message_id. When a member has never seen any message in a channel (seen_message_id is False), accessing .id threw 'TypeError: can't access property id, selfMember.seen_message_id is undefined', breaking message deletion for that user (e.g. deleting a message in a channel the user never opened. Add optional chaining on seen_message_id so the unread counter is simpl
Original PR description
The mail.message/delete bus handler accessed selfMember?.seen_message_id.id with optional chaining only on selfMember, not on seen_message_id. When a member has never seen any message in a channel (seen_message_id is False), accessing .id threw 'TypeError: can't access property id, selfMember.seen_message_id is undefined', breaking message deletion for that user (e.g. deleting a message in a channel the user never opened. Add optional chaining on seen_message_id so the unread counter is simply not decremented when no message has been seen yet. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#277417
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). task-6014315 --- I confirm I have signed the CLA and read the
Original PR description
The current implementation of the Peppol XML export incorrectly populates the <cac:InvoicePeriod> nodes with internal deferred entry dates. These dates are intended for the vendor's revenue recognition process, and the customer has nothing to do with these dates. This commit ensures that: - deferred entries are never created when importing vendor bills. - <cac:InvoicePeriod> is no longer exported in invoices (for now). task-6014315 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269491 Forward-Port-Of: odoo/odoo#265796
7 changes
Resolved issues and error corrections
Steps to reproduce: ------------------------------------ 1. Install Time off module 2. Create New Fully Flexible Employee 3. Click on the Time off smart button 4. Create time off for multiple days (eg. Mon - Friday) Observation: ------------------------------------ Number of days still shows 1 Days. Issue: ------------------------------------ Issue occurs because `work_time_per_day_mapped` returns one interval per day for standard and flexible schedules in multi-day time off requ
Original PR description
Steps to reproduce: ------------------------------------ 1. Install Time off module 2. Create New Fully Flexible Employee 3. Click on the Time off smart button 4. Create time off for multiple days…
Steps to reproduce: ------------------------------------ 1. Install Time off module 2. Create New Fully Flexible Employee 3. Click on the Time off smart button 4. Create time off for multiple days (eg. Mon - Friday) Observation: ------------------------------------ Number of days still shows 1 Days. Issue: ------------------------------------ Issue occurs because `work_time_per_day_mapped` returns one interval per day for standard and flexible schedules in multi-day time off requests, so the interval count correctly matches the number of leave days. https://github.com/odoo/odoo/blob/d73e5662a0af7c549008661f743ba5d51f765339/addons/hr_holidays/models/hr_leave.py#L460-L461 However, for fully flexible schedules, it returns a single interval containing the total hours across all days, causing the leave duration to always be computed as 1 day regardless of the actual number of days requested. Solution: ------------------------------------ For fully flexible employees, count the actual calendar days and subtract public holidays when applicable. opw-6060552
The getter `getLoadedDataSources` was filtering out datasources that are not 'ready' but they should actually filter out datasources that were already loaded (so ready) but invalid. Task: 6387729 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
Original PR description
The getter `getLoadedDataSources` was filtering out datasources that are not 'ready' but they should actually filter out datasources that were already loaded (so ready) but invalid. Task: 6387729 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
Routes inherited from product category are not available when on replenish. Steps to reproduce: ------------------- * Create a new route and allow it on product category * Create a product category and add the route * Add the category to a product * use the repenish button -> the category route is not available on the replenishment Observation: ------------- When opening replenishment, it will open the view_product_replenish, in that view, it will use allowed_route_ids to allow us
Original PR description
Routes inherited from product category are not available when on replenish. Steps to reproduce: ------------------- * Create a new route and allow it on product category * Create a product category…
Routes inherited from product category are not available when on replenish. Steps to reproduce: ------------------- * Create a new route and allow it on product category * Create a product category and add the route * Add the category to a product * use the repenish button -> the category route is not available on the replenishment Observation: ------------- When opening replenishment, it will open the view_product_replenish, in that view, it will use allowed_route_ids to allow us to choose a route for this replenishment: https://github.com/odoo/odoo/blob/2f25b2a70eca5b4f3c2e1d6c7003b1760afc0ba0/addons/stock/wizard/product_replenish_views.xml#L37 allowed_route_ids is compute in the mixin with the following domain: https://github.com/odoo/odoo/blob/2f25b2a70eca5b4f3c2e1d6c7003b1760afc0ba0/addons/stock/models/stock_replenish_mixin.py#L18-L21 https://github.com/odoo/odoo/blob/2f25b2a70eca5b4f3c2e1d6c7003b1760afc0ba0/addons/stock/models/stock_replenish_mixin.py#L25-L31 this only take into account route from the product and not the ones from the product category. https://github.com/odoo/odoo/blob/deeecf7cd02e7383b591835b0c6495e3ddead0ff/addons/stock/models/stock_location.py#L511 opw-6297308
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`)
Original PR description
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296…
### Issue: When importing EDI documents such as Peppol files, Swiss VAT numbers may be formatted or unformatted When `base_vat` is installed, VAT is stored formatted in Odoo (e.g. `CHE-530.781.296 TVA`) If the format differs, the matching fails and a new partner is created at each import ### Cause: `_retrieve_partner` lacked Swiss-specific VAT normalization logic in `_get_country_specific_vat_variants`, causing it to miss formatted variants with language suffixes (`TVA`, `MWST`, `IVA`) Even when the match succeeded, `_import_ubl_create_missing_customer` still compared VAT strings without stripping `-` and lang suffixes for CH partners, causing a false mismatch and triggering partner creation anyway ### Notes: The partner match improvement is backported from 18.3: https://github.com/odoo/odoo/commit/f1a5a3d72a26ee471d2ef1d8034136208b2bcebc The original fix was incomplete — it added `_get_country_specific_vat_variants` but missed the VAT comparison fix in `_import_ubl_create_missing_customer`, allowing the issue to persist after a successful match `base_vat` is required to get the fix fully working ### Steps to reproduce: - Install `account` and `base_vat` - Create a Vendor (Name: Test CH Vendor, Country: Switzerland, Tax ID: CHE-530.781.296 TVA) - Import a [Peppol Bill](https://github.com/user-attachments/files/27202997/CH_bill_to_import.xml) with VAT `CHE530781296TVA` Before the fix, a new partner is created instead of matching the existing one opw-6353387
Steps to reproduce: - Enable the ZUGFeRD (or Factur-X) e-invoicing format on a German customer. - Create a sale order for that customer, confirm it, create an invoice with a down payment. - Confirm and send the invoice to generate the PDF/XML. - Validate the XML (e.g. on portinvoice.com): it is rejected because the invoice line is missing the mandatory ram:Name field, only ram:Description is present. Cause of the issue: a down payment invoice line created from a sale order no l
Original PR description
Steps to reproduce: - Enable the ZUGFeRD (or Factur-X) e-invoicing format on a German customer. - Create a sale order for that customer, confirm it, create an invoice with a down payment. - Confirm and send the invoice to generate the PDF/XML. - Validate the XML (e.g. on portinvoice.com): it is rejected because the invoice line is missing the mandatory ram:Name field, only ram:Description is present. Cause of the issue: a down payment invoice line created from a sale order no longer carries a product_id: it only has a free-text. The Factur-X/CII export template rendered ram:Name directly from line.product_id.name with no fallback. For a line without a product, this produced an empty ram:Name element, which cleanup_xml_node then stripped entirely from the XML, leaving only ram:Description. Solution: Fall back to the line's name when there is no product opw-6391121
When a product's attribute uses the "multi" display type and only a single value is assigned to it, adding the product to the order added it directly, without ever showing the configuration popup. The operator was therefore unable to (de)select that value. opw-6413892 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
When a product's attribute uses the "multi" display type and only a single value is assigned to it, adding the product to the order added it directly, without ever showing the configuration popup. The operator was therefore unable to (de)select that value. opw-6413892 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
**Description of the issue/feature this PR addresses:** When some stock.picking.type records have stock.picking.batch records, the count_picking_batch displays the correct value, but when the user clicks the button, it shows a different number of records because it is not filtered by the corresponding stock.picking.type. TODO: We replace the context on the Python side because the same action is used in the menu to go to Inventory / Operations / Jobs / Batch Transfers. I think it is necessary
Original PR description
**Description of the issue/feature this PR addresses:** When some stock.picking.type records have stock.picking.batch records, the count_picking_batch displays the correct value, but when the user…
**Description of the issue/feature this PR addresses:** When some stock.picking.type records have stock.picking.batch records, the count_picking_batch displays the correct value, but when the user clicks the button, it shows a different number of records because it is not filtered by the corresponding stock.picking.type. TODO: We replace the context on the Python side because the same action is used in the menu to go to Inventory / Operations / Jobs / Batch Transfers. I think it is necessary to create a new action to use in the button, different from the one used in the menu, but due to stable policies, we avoid this change. **Current behavior before PR:** The records displayed when the user clicks the button do not match the record count indicated on the button. https://github.com/user-attachments/assets/24f23650-8161-40ec-8177-0a2898004f6f **Desired behavior after PR is merged:** The record count shown on the button matches the records displayed when the user clicks the button and opens the action. https://github.com/user-attachments/assets/3c550575-b4fa-40c9-89fc-eeedf66d069d TT60248 CC: @Tecnativa @pedrobaeza --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
5 changes
Resolved issues and error corrections
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#278667
Original PR description
Portal subscribe task can create tb because the task was archived before unsubscribing. opw-6397850 Forward-Port-Of: odoo/odoo#278667
Retrieving documents from the Peppol proxy could trigger a timeout for large databases (e.g. thousands of products or invoices with many thousands of lines), causing the cron to fail and preventing commits and ACK from being sent to the IAP server. To mitigate this, the cron runtime is limited to (limit_time_real or limit_time_real_cron) minus 60 seconds, leaving a 1-minute safety margin before the actual timeout. opw-5868249
Original PR description
Retrieving documents from the Peppol proxy could trigger a timeout for large databases (e.g. thousands of products or invoices with many thousands of lines), causing the cron to fail and preventing commits and ACK from being sent to the IAP server. To mitigate this, the cron runtime is limited to (limit_time_real or limit_time_real_cron) minus 60 seconds, leaving a 1-minute safety margin before the actual timeout. opw-5868249
The getter `getLoadedDataSources` was filtering out datasources that are not 'ready' but they should actually filter out datasources that were already loaded (so ready) but invalid. Task: 6387729 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
Original PR description
The getter `getLoadedDataSources` was filtering out datasources that are not 'ready' but they should actually filter out datasources that were already loaded (so ready) but invalid. Task: 6387729 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
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used
Original PR description
Before this commit, pressing Enter or Ctrl+Enter after editing the custom favorite filter name could save the previous value instead of the latest one. This happened because `t-model.trim` synchronizes the model on the `change` event. Since the save action is triggered on `keydown`, the latest input value had not yet been propagated to the component state. This commit removes `.trim` from `t-model` and trims the description only during the save operation, ensuring the latest value is used while preserving the existing validation against empty or whitespace-only names. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
Currently, when a search is made on the website, hybrid_list passes the search term to autocomplete. Inside the autocomplete function, a search is performed, then _search_render_results is called with all the results. The data returned from _search_render_results is then sorted and returned to hybrid_list where it's paginated. This means, if the search results in 1000 records, we call _search_render_results on all of them. This is an expensive function, and much of it goes to waste if i
Original PR description
Currently, when a search is made on the website, hybrid_list passes the search term to autocomplete. Inside the autocomplete function, a search is performed, then _search_render_results is called…
Currently, when a search is made on the website, hybrid_list passes the search term to autocomplete. Inside the autocomplete function, a search is performed, then _search_render_results is called with all the results. The data returned from _search_render_results is then sorted and returned to hybrid_list where it's paginated. This means, if the search results in 1000 records, we call _search_render_results on all of them. This is an expensive function, and much of it goes to waste if it's not the 50 products shown on the page. This change sorts and paginates the records inside autocomplete before running _search_render_results on the subset of 50 records that will eventually be shown on the current page. This optimizes the search by making the maximum recordset size _search_render_results is run on to be 50, down from an unbounded number scaling with products in the database. The default cap for the number of search results is 500. | | 42 Results | 500 Results (Cap) | 1,000 Results | 35,000 results | | --- | --- | --- | --- | --- | | Queries Before | 195 | 1515 | 3191 | memory error | | Queries After | 195 | 209 | 210 | 251 | | Time Before | 3.62 | 4.50 | 5.92 | memory error | | Time After | 3.75 | 2.78 | 1.98 | 2.67 | Note: The differences in timing can be attributed to the initial query time for `_search_with_fuzzy` opw-6381030