Daily updates from Odoo
Tuesday, August 4, 2026
341 changes
8 changes
Resolved issues and error corrections
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the co
Original PR description
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user…
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the contact's parent) are loaded and then written. Some of these fields may have access rights that the user trying to import doesn't have. As a result, when trying to load/write them, the user may get an error. Solution: Use sudo() when loading them. This shouldn't be an issue since they are only copied from the parent. Also, sudo() is already being used when writing the values, https://github.com/odoo/odoo/blob/bb94f13b38f0bf1ce8886f4630ad42caf6c56325/odoo/addons/base/models/res_partner.py#L996 so sudo() should also be used when loading them. opw-6396086 Forward-Port-Of: odoo/odoo#278638
In POS receipt and invoice during a B2C transaction, if the vat number was not set/ wrong, QR code was generated. This commit removes the qr code generation when the invoice is in rejected state. Also, in 19.2 in POS we displayed errors after pressing the validation button, this commit brings it back. task-6237427 Forward-Port-Of: odoo/odoo#273707
Original PR description
In POS receipt and invoice during a B2C transaction, if the vat number was not set/ wrong, QR code was generated. This commit removes the qr code generation when the invoice is in rejected state. Also, in 19.2 in POS we displayed errors after pressing the validation button, this commit brings it back. task-6237427 Forward-Port-Of: odoo/odoo#273707
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`. When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)` Because `email_to` is `False` for internal p
Original PR description
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is…
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`.
When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)`
Because `email_to` is `False` for internal partners, `('outgoing_email_to', '=', False)` evaluated to `True` against the first recipient's message record. Consequently, the search falsely determined that the second recipient was already notified, suppressing OOO replies for all subsequent contacts across the 4-day window.
## Proposed solution:
We resolve this by dynamically constructing recipient sub-domains conditionally depending if `recipient` or `email_to` are set.
We also extend `test_routing_with_out_of_office` with a corresponding test case.
## How to reproduce:
1. Set up a DB with at least 3 users (User A, User B, User C).
2. Configure User A to be out of office (in user preferences)
3. Go to any chatter/mail.thread while logged as User B and tag User A in a log note. -> triggers OOO message
4. Log as User C, tag User A in a log note. -> BUG: no OOO message because the "4 day" check falsely believes that User C already received a OOO from User A
OPW-6110300
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279881
Forward-Port-Of: odoo/odoo#277880Steps to reproduce ------------------ 1. Set two receipt printers on the PoS and open it. 2. From another tab, remove one of the printers and save. -> the open PoS still shows the old printers. It only updates after "reload data" or reopening the session. Why the issue ------------- The open PoS keeps the printer list it loaded at the start. A normal refresh does not fetch the config again (the PoS reads its local copy), so a printer change from another tab is not seen until the data
Original PR description
Steps to reproduce ------------------ 1. Set two receipt printers on the PoS and open it. 2. From another tab, remove one of the printers and save. -> the open PoS still shows the old printers. It only updates after "reload data" or reopening the session. Why the issue ------------- The open PoS keeps the printer list it loaded at the start. A normal refresh does not fetch the config again (the PoS reads its local copy), so a printer change from another tab is not seen until the data is reloaded. The fix ------- When the receipt or preparation printers change on the config, we send a notification to the open PoS sessions with the new printers. The PoS updates its printer list on the spot, without needing to reloade any ohter data. opw-6351006
Before this commit: ===================== floating orders could show the same order number twice on the POS receipt: once through the floating order name and once through the tracking number. This happened because the floating order name defaults to the tracking number until a cashier manually sets a custom name. After this commit: =================== The receipt only displays the floating order name when it differs from the tracking number. Task-6394222 Forward-Port-Of: odoo/odoo#277
Original PR description
Before this commit: ===================== floating orders could show the same order number twice on the POS receipt: once through the floating order name and once through the tracking number. This happened because the floating order name defaults to the tracking number until a cashier manually sets a custom name. After this commit: =================== The receipt only displays the floating order name when it differs from the tracking number. Task-6394222 Forward-Port-Of: odoo/odoo#277492
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://gith
Original PR description
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g.,…
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://github.com/odoo/odoo/blob/c1acf61ab23f231e416354a3504cc3c18170af2c/addons/hr_holidays/static/src/components/float_time_selection/float_time_selection.js#L45-L56 Here, the code attempts to parse the hours and minutes by splitting the already localized formatted string (super.formattedValue) and checking if the formatted value ended with "h" or "m". In Dutch, the localized string ends with "u" instead of "h", causing the string-matching logic to fail silently and default back to 0 (12 a.m.). Example: If we change the value to 10:30 AM, in Dutch the formatted value becomes "10u 30m". Reference: e80750d Solution: --------- Stop parsing the localized formatted string and instead compute hours and minutes directly from the float value stored in the record using `floatToHoursMinutes`, making the formatting independent of translations. opw-6303884 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271085
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people,
Original PR description
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but…
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people, since they would access the page so often, google automatically fill up the url when they type odoo to odoo/web/login This commit aims to introduce a link to the home page that will be displayed in the warning message. This way cusotmers can get to the home page, and we will hopefully stop the support tickets this has created opw-6331783 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274999
Miscellaneous changes
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclus
Original PR description
Optimize search_paid_order_ids to reduce ORM overhead and resolve a database bottleneck during POS synchronization. - Move currency validation from a Python post-filter into the SQL domain via config_id.currency_id. - Split the costly OR query on pos.order.line into two targeted index scans combined via UNION, dropping execution time from ~627ms to ~16ms (~40x speedup) and reducing shared read blocks from 650k+ to zero. - Align totalCount with the exact same domain and simplify state exclusions from multiple != operators to a single not in. Explain Before: https://explain.dalibo.com/plan/84095dcgfdc158a2 Explain After: https://explain.dalibo.com/plan/ag2abcdf4ge5d5e5 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279595 Forward-Port-Of: odoo/odoo#278739
9 changes
Resolved issues and error corrections
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the co
Original PR description
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user…
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the contact's parent) are loaded and then written. Some of these fields may have access rights that the user trying to import doesn't have. As a result, when trying to load/write them, the user may get an error. Solution: Use sudo() when loading them. This shouldn't be an issue since they are only copied from the parent. Also, sudo() is already being used when writing the values, https://github.com/odoo/odoo/blob/bb94f13b38f0bf1ce8886f4630ad42caf6c56325/odoo/addons/base/models/res_partner.py#L996 so sudo() should also be used when loading them. opw-6396086 Forward-Port-Of: odoo/odoo#278638
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`. When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)` Because `email_to` is `False` for internal p
Original PR description
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is…
When an internal recipient receives an Out of Office (OOO) notification, the resulting `mail.message` record has `partner_ids` populated with the recipient partner ID, while `outgoing_email_to` is set to `False`.
When a second internal user emails the OOO user within the 4-day window, `_notify_thread_with_out_of_office` excutes a search domain with an OR condition: `'|', ('partner_ids', 'in', recipient.ids), ('outgoing_email_to', '=', email_to)`
Because `email_to` is `False` for internal partners, `('outgoing_email_to', '=', False)` evaluated to `True` against the first recipient's message record. Consequently, the search falsely determined that the second recipient was already notified, suppressing OOO replies for all subsequent contacts across the 4-day window.
## Proposed solution:
We resolve this by dynamically constructing recipient sub-domains conditionally depending if `recipient` or `email_to` are set.
We also extend `test_routing_with_out_of_office` with a corresponding test case.
## How to reproduce:
1. Set up a DB with at least 3 users (User A, User B, User C).
2. Configure User A to be out of office (in user preferences)
3. Go to any chatter/mail.thread while logged as User B and tag User A in a log note. -> triggers OOO message
4. Log as User C, tag User A in a log note. -> BUG: no OOO message because the "4 day" check falsely believes that User C already received a OOO from User A
OPW-6110300
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#279881
Forward-Port-Of: odoo/odoo#277880Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://gith
Original PR description
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g.,…
Steps to reproduce: ------------------- 1. Install hr_holidays. 2. Create a new Time Off Type with "Duration type" set to Hours. 3. Create a time off request. 4. Change the default hour value (e.g., from 12 AM to 10 AM) and observe the formatted value. 5. Switch the user language to Dutch. 6. Create another time off request and change the hour value to 10 AM. Issue: ------ After changing the value to 10 AM, the displayed formatted value remains 12 a.m. Cause: ------ https://github.com/odoo/odoo/blob/c1acf61ab23f231e416354a3504cc3c18170af2c/addons/hr_holidays/static/src/components/float_time_selection/float_time_selection.js#L45-L56 Here, the code attempts to parse the hours and minutes by splitting the already localized formatted string (super.formattedValue) and checking if the formatted value ended with "h" or "m". In Dutch, the localized string ends with "u" instead of "h", causing the string-matching logic to fail silently and default back to 0 (12 a.m.). Example: If we change the value to 10:30 AM, in Dutch the formatted value becomes "10u 30m". Reference: e80750d Solution: --------- Stop parsing the localized formatted string and instead compute hours and minutes directly from the float value stored in the record using `floatToHoursMinutes`, making the formatting independent of translations. opw-6303884 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271085
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a `production_id` in Move History (shown in gray in 18.3+ instead of colored) ### Cause: `production_id` is set on move lines in `_action_assign`, overridden in `mrp` to propagate MO-specific data: https://github.com/odoo/odoo/blob/e8d4ea2dc71109e9afc5b894c9359bcfc08295ae/addons/mrp/models/stock_mov
Original PR description
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a…
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a `production_id` in Move History (shown in gray in 18.3+ instead of colored) ### Cause: `production_id` is set on move lines in `_action_assign`, overridden in `mrp` to propagate MO-specific data: https://github.com/odoo/odoo/blob/e8d4ea2dc71109e9afc5b894c9359bcfc08295ae/addons/mrp/models/stock_move.py#L352-L358 In the normal flow, `_action_assign` is called by `_action_confirm` on the `stock.move`: https://github.com/odoo/odoo/blob/737e28b9c8609d488d93ce7ce05941ff93779e04/addons/stock/models/stock_move.py#L1644-L1646 But when a line is added manually, the move is already created with state `assigned`, so `_action_confirm` skips the call and `_action_assign` is never executed ### Fix: Setting `production_id` in `_action_assign` was incorrectly placed — there is no reason to set it during move assignment Moving it to the move line creation avoids the issue entirely and removes the dependency on a code path that may not be triggered ### Steps to reproduce: - Install `mrp` - Create a BoM for a tracked product with 2 tracked components - Enable Developer mode - Create a Manufacturing Order for the product - Unhide the View button on a component move and click it - Add a new line for the first component (qty: 1) - Confirm and Produce All the MO - Go to Inventory > Reporting > Move History - Add `production_id` via Studio (or check line color in 18.3+) Before the fix, the manually added line has no `production_id` (and in 18.3+ the line is gray instead of colored) opw-6250911 Forward-Port-Of: odoo/odoo#279839 Forward-Port-Of: odoo/odoo#272035
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on editing the description -> Observe that the description is partially hidden because the widget height is incorrectly computed **Cause** Since commit https://github.com/odoo/odoo/commit/e4f4171e1bc838840c0bd6111cd78f348b201ac2, `useProductAndLabelAutoresize` no longer assigns a height to the
Original PR description
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on…
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on editing the description -> Observe that the description is partially hidden because the widget height is incorrectly computed **Cause** Since commit https://github.com/odoo/odoo/commit/e4f4171e1bc838840c0bd6111cd78f348b201ac2, `useProductAndLabelAutoresize` no longer assigns a height to the widget root. The corresponding widget is `MoveProductLabelField`, which extends `ProductNameAndDescriptionField`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/stock/static/src/views/picking_form/stock_move_product_label.js#L5 It uses `useProductAndLabelAutoresize`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/product/static/src/product_name_and_description/product_name_and_description.js#L54-L56 **Solution** Explicitly add a div around the product display and description to still use the `Autoresize` Forward-Port-Of: odoo/odoo#271564
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people,
Original PR description
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but…
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people, since they would access the page so often, google automatically fill up the url when they type odoo to odoo/web/login This commit aims to introduce a link to the home page that will be displayed in the warning message. This way cusotmers can get to the home page, and we will hopefully stop the support tickets this has created opw-6331783 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274999
When a format is applied on an unsplittable node, removing it from a wider selection does not dare to touch that format to ensure it won't be split. Because of this, it becomes impossible to remove the format on such nodes. This commit slightly adapts the logic by so that instead of stopping when encountering an unsplittable node, it keeps looking higher in the hierarchy where the format is actually defined. Steps to reproduce: - Go to a "To do" note - Select a word - Apply a style (un
Original PR description
When a format is applied on an unsplittable node, removing it from a wider selection does not dare to touch that format to ensure it won't be split. Because of this, it becomes impossible to remove the format on such nodes. This commit slightly adapts the logic by so that instead of stopping when encountering an unsplittable node, it keeps looking higher in the hierarchy where the format is actually defined. Steps to reproduce: - Go to a "To do" note - Select a word - Apply a style (underscore, strikethrough...) - Type "odoo.com" - Press space to turn it into a link - Select the whole line - Try to remove the style => The style was not removed from the link. task-6322596 Forward-Port-Of: odoo/odoo#279947 Forward-Port-Of: odoo/odoo#273922
Before this commit, when a product had a multi choice attribute with only one option, it was not possible to configure the product in the POS or in the self. This is a problem since multi choice are different from other attribute display type because their options are opttional. The user should thus be able to select if he wants the option or not so we should display the configurator even if there is only one option. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.
Original PR description
Before this commit, when a product had a multi choice attribute with only one option, it was not possible to configure the product in the POS or in the self. This is a problem since multi choice are different from other attribute display type because their options are opttional. The user should thus be able to select if he wants the option or not so we should display the configurator even if there is only one option. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#271287
Restore the previous behavior by calling `checkAccessRight()` without awaiting it during `PosStore.setup()`. This prevents the POS startup from being blocked while the access check is running. This fixes PoS startup and offline fallback tours timing out while waiting for the "Continue with limited functionality" dialog. Runbot Error-[944421](https://runbot.odoo.com/odoo/error/944421) Forward-Port-Of: odoo/odoo#279792 Forward-Port-Of: odoo/odoo#278628
Original PR description
Restore the previous behavior by calling `checkAccessRight()` without awaiting it during `PosStore.setup()`. This prevents the POS startup from being blocked while the access check is running. This fixes PoS startup and offline fallback tours timing out while waiting for the "Continue with limited functionality" dialog. Runbot Error-[944421](https://runbot.odoo.com/odoo/error/944421) Forward-Port-Of: odoo/odoo#279792 Forward-Port-Of: odoo/odoo#278628
16 changes
Resolved issues and error corrections
Issue: --- If a product template has dynamic attributes, some variants might not exist. For those variants, we are showing wrong stock in the website. To reproduce: 1- Create a product with a dynamic attribute and two values. 2- Publish the product and uncheck sell when out-of-stock and check show product when the qty is less than 5. 3- Create a purchase order with qty = 4 for the first value, so a variant is created for it. 4- Go to the website shop. Open the product. 4 available qty i
Original PR description
Issue: --- If a product template has dynamic attributes, some variants might not exist. For those variants, we are showing wrong stock in the website. To reproduce: 1- Create a product with a dynamic attribute and two values. 2- Publish the product and uncheck sell when out-of-stock and check show product when the qty is less than 5. 3- Create a purchase order with qty = 4 for the first value, so a variant is created for it. 4- Go to the website shop. Open the product. 4 available qty in stock is shown for the first variant which is correct. 5- Select 2nd variant. As you see, still 4 available qty is shown which is wrong. As the out-of-stock sale is unchecked, an out-of-stock warning should be shown. Cause and Fix: --- This is due to `isMainProduct` being always False when `product_id` is not set which makes `free_qty` and `out_of_stock` not to be updated. opw-6237602 Forward-Port-Of: odoo/odoo#279572 Forward-Port-Of: odoo/odoo#273104
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a `production_id` in Move History (shown in gray in 18.3+ instead of colored) ### Cause: `production_id` is set on move lines in `_action_assign`, overridden in `mrp` to propagate MO-specific data: https://github.com/odoo/odoo/blob/e8d4ea2dc71109e9afc5b894c9359bcfc08295ae/addons/mrp/models/stock_mov
Original PR description
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a…
### Issue: When a `stock.move.line` is manually added to a component move of a Manufacturing Order via the debug View button, it is not linked to the MO This causes the line to appear without a `production_id` in Move History (shown in gray in 18.3+ instead of colored) ### Cause: `production_id` is set on move lines in `_action_assign`, overridden in `mrp` to propagate MO-specific data: https://github.com/odoo/odoo/blob/e8d4ea2dc71109e9afc5b894c9359bcfc08295ae/addons/mrp/models/stock_move.py#L352-L358 In the normal flow, `_action_assign` is called by `_action_confirm` on the `stock.move`: https://github.com/odoo/odoo/blob/737e28b9c8609d488d93ce7ce05941ff93779e04/addons/stock/models/stock_move.py#L1644-L1646 But when a line is added manually, the move is already created with state `assigned`, so `_action_confirm` skips the call and `_action_assign` is never executed ### Fix: Setting `production_id` in `_action_assign` was incorrectly placed — there is no reason to set it during move assignment Moving it to the move line creation avoids the issue entirely and removes the dependency on a code path that may not be triggered ### Steps to reproduce: - Install `mrp` - Create a BoM for a tracked product with 2 tracked components - Enable Developer mode - Create a Manufacturing Order for the product - Unhide the View button on a component move and click it - Add a new line for the first component (qty: 1) - Confirm and Produce All the MO - Go to Inventory > Reporting > Move History - Add `production_id` via Studio (or check line color in 18.3+) Before the fix, the manually added line has no `production_id` (and in 18.3+ the line is gray instead of colored) opw-6250911 Forward-Port-Of: odoo/odoo#272035
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: - "Component" - "Final" with a bom containing "Component" and tracked by Serial number - "Setup" with a bom containing "Final" * Create and confirm a MO for "Setup" - assign the serial number "PROD" to "Final" * Produce "Setup" * Create and confirm a MO for "Final" * Generate a seria
Original PR description
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: -…
In a MO for a product tracked by serial number, when changing the serial number after confirming the mo, it will silently assign a serial number. **Steps to reproduce** * Create three products: - "Component" - "Final" with a bom containing "Component" and tracked by Serial number - "Setup" with a bom containing "Final" * Create and confirm a MO for "Setup" - assign the serial number "PROD" to "Final" * Produce "Setup" * Create and confirm a MO for "Final" * Generate a serial number * Clear the serial number * Generate a new serial number * Produce "Final" -> In Product Moves you can see that the serial number assign was "PROD" **Observation** First when creating the MO, it will create a stock move for "final" and create a stock move line without assigning any quant. action_confirm -> _action_assign https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_move.py#L1643-L1646 In _action_assign it will bypass_reservation since the location is "production": https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_move.py#L1948 https://github.com/odoo/odoo/blob/ff0dd8fcc8dfbb5e5cb798c90d68be41d56b7b4c/addons/stock/models/stock_location.py#L411-L413 and create the sml: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/stock/models/stock_move.py#L2048 When adding the Serial number it will be added to lot_producing_ids, set qty_producing and call set_qty_producing ->_set_quantity_done -> _set_quantity_done_prepare_vals: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/mrp/models/mrp_production.py#L1593-L1597 In set_qty_producing->_set_quantity_done ->_set_quantity_done_prepare_vals nothing will be done since there already is a stock move line with the right quantity: https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/stock/models/stock_move.py#L2368-L2371 Second when clearing the Serial number it will call action_clear_lot_producing_ids, where it will - Erase the lot from lot_producing_ids - Set qty_producing to 0 - and call _set_qty_producing _set_qty_producing -> _set_quantity_done -> _set_quantity_done_prepare_vals: where it will erase the stock move line since it's new quantity is 0: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/stock/models/stock_move.py#L2353-L2355 Lastly this means that when add in the new lot, it will not already have a stock move line, and it will create a new stock move line based on available quants: https://github.com/odoo/odoo/blob/3a088e23d3e563c39cdcb252edc8c7cc74981de4/addons/stock/models/stock_move.py#L2392-L2402 The lot_ids on the moves is supposed the get assigned when we produce the product: https://github.com/odoo/odoo/blob/e8aa9219e3c72a987f431e47a1534f9ccb0028b2/addons/mrp/models/mrp_production.py#L1911-L1913 opw-6240857 Forward-Port-Of: odoo/odoo#268542
### Problem When mass updating the “Analytic Distribution” field on the lines on Analytic Items the values are not timely reflected on the lines. Steps to reproduce the issue: 1. Accounting > Accounting > Analytic Items. 2. Select multiple records (lines) from the list view. 3. Click on the "Analytic Distribution" column for one of the selected lines to mass-update it. 4. Add or adjust a specific analytic account/tag and click away to apply. 5. Click "Update" on the confirmation pop-up.
Original PR description
### Problem When mass updating the “Analytic Distribution” field on the lines on Analytic Items the values are not timely reflected on the lines. Steps to reproduce the issue: 1. Accounting > Accounting > Analytic Items. 2. Select multiple records (lines) from the list view. 3. Click on the "Analytic Distribution" column for one of the selected lines to mass-update it. 4. Add or adjust a specific analytic account/tag and click away to apply. 5. Click "Update" on the confirmation pop-up. 6. The previously existing analytic distribution tags of other plans disappear, showing only the newly updated account/tag. 7. Refresh the page. 8. The "missing" tags reappear alongside the newly updated one. ### Solution We need to trigger a read of the updated values after they are saved on the server side. opw-6045687 Forward-Port-Of: odoo/odoo#275497 Forward-Port-Of: odoo/odoo#261068
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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.odo
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 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#278123
## Problem When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total. ## Solution When retreiving the relevant moves for quantity calculation (_get_outgoing_incoming_moves), we will filter out any moves not belonging to the SOL's company. This will prevent moves from other companies into the interco location from being counted towards qty_delivered. ## Steps to Replicate (runbot v19) 1. Create a route
Original PR description
## Problem When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total. ## Solution When retreiving the relevant moves…
## Problem
When computing qty_delivered on a sale order line, intercompany 'delieveries' from the other company would count towards the delivery total.
## Solution
When retreiving the relevant moves for quantity calculation (_get_outgoing_incoming_moves), we will filter out any moves not belonging to the SOL's company. This will prevent moves from other companies into the interco location from being counted towards qty_delivered.
## Steps to Replicate (runbot v19)
1. Create a route
- Pull Comp B -> Interco, MTO, Comp B delivery
- Pull Interco -> Comp A, MTS, Comp A receipt
(You can review the test for more info about this route config)
(There is also this video showcasing the issue on runbot: https://drive.google.com/file/d/1YeUie4EhWPyg_RuJkNf40S9zARB4jXWY/view)
2. Attach a product to this new route
3. Create a SO for the product and confirm it
4. You should see 4 pickings, validate the chain
5. The qty_delivered on the sale order is double the demand
opw-6361559
Forward-Port-Of: odoo/odoo#275694**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on editing the description -> Observe that the description is partially hidden because the widget height is incorrectly computed **Cause** Since commit https://github.com/odoo/odoo/commit/e4f4171e1bc838840c0bd6111cd78f348b201ac2, `useProductAndLabelAutoresize` no longer assigns a height to the
Original PR description
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on…
**Issue** The height is not correctly computed in the picking form when editing product description. **Steps to reproduce** - Create a delivery for a product - Add a description to it - Click on editing the description -> Observe that the description is partially hidden because the widget height is incorrectly computed **Cause** Since commit https://github.com/odoo/odoo/commit/e4f4171e1bc838840c0bd6111cd78f348b201ac2, `useProductAndLabelAutoresize` no longer assigns a height to the widget root. The corresponding widget is `MoveProductLabelField`, which extends `ProductNameAndDescriptionField`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/stock/static/src/views/picking_form/stock_move_product_label.js#L5 It uses `useProductAndLabelAutoresize`: https://github.com/odoo/odoo/blob/91b59f285248c120fe9e3e5f6b6f086ea7be2837/addons/product/static/src/product_name_and_description/product_name_and_description.js#L54-L56 **Solution** Explicitly add a div around the product display and description to still use the `Autoresize` Forward-Port-Of: odoo/odoo#271564
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js`, allowing the next tour step to run before the loader was shown. After this commit, the tour waits for `o_loading_screen`, which is added immediately and remains visible until the operation finishes. T
Original PR description
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for…
### 1. Prevent tour failure by waiting on the correct loading class Before this PR, the tour introduced in commit [1] and modified in commit [2] could fail non-deterministically because it waited for `o_we_ui_loading` to disappear. However, this class was added with a delay in `operation.js`, allowing the next tour step to run before the loader was shown. After this commit, the tour waits for `o_loading_screen`, which is added immediately and remains visible until the operation finishes. This ensures that the tour waits correctly before proceeding. [1]: https://github.com/odoo/odoo/commit/091b8dee407fe30a115d4bb2e96d4d [2]: https://github.com/odoo/odoo/commit/544a03775119021442d66486c24711 **runbot:** [941508](https://runbot.odoo.com/odoo/error/941508) --- ### 2. Prevent tour failure by clicking the "Close" button instead of pressing "Escape" Before this PR, the tour step introduced in commit [1], which pressed the <kbd>Escape</kbd> key to close the Insert Snippet dialog, could fail non-deterministically with the error: > It is not allowed to do action on an element that's below a modal. After this PR, instead of pressing <kbd>Escape</kbd>, the tour clicks the **Close** (`X`) button to close the dialog. This is a more reliable way to close the dialog and prevents the non-deterministic failure of the sync color shape tour. [1]: https://github.com/odoo/odoo/commit/544a03775119021442d66486c24711d **runbot:** [944543](https://runbot.odoo.com/odoo/error/944543) --- ### 3. Prevent tour failure by adding steps to open sliding panel for color-related options Before this PR, the tour introduced in commit [1] and modified in commit [2] was breaking, because it expected the color-related options to be directly available under the theme tab. However, after commit [3], the color-related controls were moved into a sliding panel. This PR adds the missing steps to open the sliding panel before accessing the color-related options, allowing the tour to complete successfully. [3]: https://github.com/odoo/odoo/commit/8e104a3a416781a903f3b3b4b77e5f8be24fc7b0 **runbot:** [944587](https://runbot.odoo.com/odoo/error/944587) Forward-Port-Of: odoo/odoo#279395 Forward-Port-Of: odoo/odoo#278743
When selecting a new microphone or camera in the `Voice & Video settings` outside an active meeting, the browser was not asking for permission immediately. This caused Firefox (which enforces per device permissions) to reprompt when the meeting started. This fix pre-authorizes the selected device, so Firefox prompts at selection time rather than when starting a meeting. task-6175062 Forward-Port-Of: odoo/odoo#279624 Forward-Port-Of: odoo/odoo#277730
Original PR description
When selecting a new microphone or camera in the `Voice & Video settings` outside an active meeting, the browser was not asking for permission immediately. This caused Firefox (which enforces per device permissions) to reprompt when the meeting started. This fix pre-authorizes the selected device, so Firefox prompts at selection time rather than when starting a meeting. task-6175062 Forward-Port-Of: odoo/odoo#279624 Forward-Port-Of: odoo/odoo#277730
Issue: Outstanding credits/debits from a branch don't appear on the main company and inversely. Cause : From odoo/odoo#255875 outstanding credits/debits are limited by company to prevent different company issues on validation. However, this error is raised for `account.move` having different root companies. Which allow move from different branches of the same company. Steps to reproduce: - create a company and a branch - in the main company create a customer payment and valid it - in
Original PR description
Issue: Outstanding credits/debits from a branch don't appear on the main company and inversely. Cause : From odoo/odoo#255875 outstanding credits/debits are limited by company to prevent different company issues on validation. However, this error is raised for `account.move` having different root companies. Which allow move from different branches of the same company. Steps to reproduce: - create a company and a branch - in the main company create a customer payment and valid it - in the branch, create an invoice for the same customer and confirm it Current behavior: - the outstanding payment from the main company doesn't appear on the branch invoice, However, it's possible to reconcile it from the Journal entry view Expected behavior: - the outstanding payment from the main company appears on the branch invoice, opw-6140689 Forward-Port-Of: odoo/odoo#262260
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 Forward-Port-Of: odoo/odoo#277418
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people,
Original PR description
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but…
recently in 19.1 a commit adds a warning and disables the button in the signup for if you are alreafy logged in. The issue is that for websites without the header (which is the case for internal, but can happen to customers) there is no way to get to the homepage (except from writing to the url or hiting the back button) This created an issue in internal as an example, since our customers have aparently bookmarked the login page, and they would simply login again before this. For some people, since they would access the page so often, google automatically fill up the url when they type odoo to odoo/web/login This commit aims to introduce a link to the home page that will be displayed in the warning message. This way cusotmers can get to the home page, and we will hopefully stop the support tickets this has created opw-6331783 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#274999
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the co
Original PR description
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user…
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the contact's parent) are loaded and then written. Some of these fields may have access rights that the user trying to import doesn't have. As a result, when trying to load/write them, the user may get an error. Solution: Use sudo() when loading them. This shouldn't be an issue since they are only copied from the parent. Also, sudo() is already being used when writing the values, https://github.com/odoo/odoo/blob/bb94f13b38f0bf1ce8886f4630ad42caf6c56325/odoo/addons/base/models/res_partner.py#L996 so sudo() should also be used when loading them. opw-6396086 Forward-Port-Of: odoo/odoo#278638
In the Point of Sale receipt styles, the margin classes ms-* (margin left) and me-* (margin right) were inverted: - me-* was pushing margins to the left. - ms-* was pushing margins to the right. This commit swaps them back to their correct sides to ensure custom tickets layout correctly. task-id: 6250233 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
In the Point of Sale receipt styles, the margin classes ms-* (margin left) and me-* (margin right) were inverted: - me-* was pushing margins to the left. - ms-* was pushing margins to the right. This commit swaps them back to their correct sides to ensure custom tickets layout correctly. task-id: 6250233 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Miscellaneous changes
Simplified version of https://github.com/odoo/odoo/pull/276689 Forward-Port-Of: odoo/odoo#277083 Forward-Port-Of: odoo/odoo#276696
Original PR description
Simplified version of https://github.com/odoo/odoo/pull/276689 Forward-Port-Of: odoo/odoo#277083 Forward-Port-Of: odoo/odoo#276696
- before ~15s: https://explain.dalibo.com/plan/45a62e3c62465e4c - after <1ms: https://explain.dalibo.com/plan/f04c6ge8ec962723 task-6396053 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Original PR description
- before ~15s: https://explain.dalibo.com/plan/45a62e3c62465e4c - after <1ms: https://explain.dalibo.com/plan/f04c6ge8ec962723 task-6396053 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
10 changes
Enhancements to existing features
Currently, Peppol product detection relies strictly on barcode or default_code matching, which fails when vendors use their own codes. Accurate product identification is essential before running the predictive model (for taxes/accounts) and is a strict prerequisite for Purchase Orders matching to function correctly. This PR makes the product matching relies on the Vendor Product Code as the first priority ( SellersItemIdentification or StandardItemIdentification or BuyersItemIdentification
Original PR description
Currently, Peppol product detection relies strictly on barcode or default_code matching, which fails when vendors use their own codes. Accurate product identification is essential before running the predictive model (for taxes/accounts) and is a strict prerequisite for Purchase Orders matching to function correctly. This PR makes the product matching relies on the Vendor Product Code as the first priority ( SellersItemIdentification or StandardItemIdentification or BuyersItemIdentification ) task-6171251 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#262801
Resolved issues and error corrections
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the co
Original PR description
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user…
Problem: When testing the import of contacts with a user without accounting access rights, the test fails and leads to an error. Steps to reproduce: 1- Remove accounting access rights from your user (Set Accounting to No) 2- Open Contacts app 3- Try importing contacts (you can download the available template and use it as the file you are asked to upload) 4- Test the import 5- Notice the error you receive Cause: When importing contacts, the commercial fields (fields related to the contact's parent) are loaded and then written. Some of these fields may have access rights that the user trying to import doesn't have. As a result, when trying to load/write them, the user may get an error. Solution: Use sudo() when loading them. This shouldn't be an issue since they are only copied from the parent. Also, sudo() is already being used when writing the values, https://github.com/odoo/odoo/blob/bb94f13b38f0bf1ce8886f4630ad42caf6c56325/odoo/addons/base/models/res_partner.py#L996 so sudo() should also be used when loading them. opw-6396086 Forward-Port-Of: odoo/odoo#278638
PoS loads product categories from both the PoS configuration and the preparation printers. Before this commit, if a child category was included in the PoS configuration, but its parent was only included in a preparation printer, the parent category was loaded in the frontend without being visible. As a result, the child category was also hidden, even though its products were still available. How to reproduce: - Create a parent category. - Create a child category containing a product. -
Original PR description
PoS loads product categories from both the PoS configuration and the preparation printers. Before this commit, if a child category was included in the PoS configuration, but its parent was only included in a preparation printer, the parent category was loaded in the frontend without being visible. As a result, the child category was also hidden, even though its products were still available. How to reproduce: - Create a parent category. - Create a child category containing a product. - Limit the PoS categories to the child category. - Create a preparation printer and assign the parent category to it. - Open the PoS. - The products are available, but the child category is not visible. opw-6381119 Forward-Port-Of: odoo/odoo#276782
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ##
Original PR description
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ### Cause of the issue: Issue comes from this commit 9396790e9cc1ce1c6e5c29b71b5629b31fb16458 where it has been forgotten to disable the translation. ### Reason to introduce the fix: Meet the requirements of the electronic invoice. opw-6023971 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273042
Use "VAT" instead of "TAX" for the default UK tax groups. Also set "Subtotal" as their preceding subtotal label so that it replaces "Untaxed Amount". task-[6413495](https://www.odoo.com/odoo/project/967/tasks/6413495) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279865 Forward-Port-Of: odoo/odoo#278351
Original PR description
Use "VAT" instead of "TAX" for the default UK tax groups. Also set "Subtotal" as their preceding subtotal label so that it replaces "Untaxed Amount". task-[6413495](https://www.odoo.com/odoo/project/967/tasks/6413495) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279865 Forward-Port-Of: odoo/odoo#278351
…F fetch Nilvera PDF retrieval (the manual "Get PDF" action and the scheduled "retrieve sale PDFs" cron) hardcoded the "Sale" document category. That is correct for e-invoices (/einvoice/Sale/{uuid}/pdf) but wrong for e-archive documents, whose resource is "Invoices". For e-archive invoices it produced GET /earchive/Sale/{uuid}/pdf, which Nilvera answers with 404, surfacing to the user as "Odoo could not perform this action at the moment... Not Found - 404" and making the cron raise on every
Original PR description
…F fetch
Nilvera PDF retrieval (the manual "Get PDF" action and the scheduled "retrieve sale PDFs" cron) hardcoded the "Sale" document category. That is correct for e-invoices (/einvoice/Sale/{uuid}/pdf) but wrong for e-archive documents, whose resource is "Invoices". For e-archive invoices it produced GET /earchive/Sale/{uuid}/pdf, which Nilvera answers with 404, surfacing to the user as "Odoo could not perform this action at the moment... Not Found - 404" and making the cron raise on every run.
Derive the document category from the invoice channel so e-archive resolves to /earchive/invoices/{uuid}/pdf while e-invoice keeps using /einvoice/sale/{uuid}/pdf.
OPW-6311661
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#278796**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution is not automatically applied to the order line. This occurs due to a previous commit that attempted to protect manually entered analytic distributions from being overwritten when an SO is confirmed and a project is generated. To do this, the old code filtered out any non-empty project lines and
Original PR description
**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution…
**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution is not automatically applied to the order line. This occurs due to a previous commit that attempted to protect manually entered analytic distributions from being overwritten when an SO is confirmed and a project is generated. To do this, the old code filtered out any non-empty project lines and bypassed calling `super()` on them. Consequently, if a line already had an analytic distribution (such as inheriting the project's), the system would skip computing the product's specific distribution rules entirely. This commit resolves the issue by reverting that change, ensuring the base compute method is always called so product-based rules execute correctly. While this means manual analytic entries added before the compute trigger might be overwritten, there is no perfect solution to prevent losing both manual and product distributions. As concluded with the Product Owner in a similar PR for Purchase Orders, we prioritize keeping the product's automated distribution, as it is much harder to manually reconstruct after its removal. The corresponding test is also reverted to its original state to reflect this expected behavior. A small test is added to ensure that the analytic distribution results are unchanged when adding a project to the SO. opw-6279406 **Steps to Reproduce:** - Accounting > Configuration > Settings > Analytics > enable Analytic Accounting - Accounting > Configuration > Analytic Accounting > Analytic Distribution Models - Create a new model with any product (e.g. “Bolt”) and any Analytic Distribution (e.g. “Production”) - Create SO, enable “Analytic Distribution” in filters - Add any customer, add the above product (e.g. “Bolt”), save - Observe that the “Production” Analytic Distribution is automatically populated - On the same SO > Other Info> Project > add (e.g. “Home Construction”) - Then go back to Order Lines and remove the previous SOL and create a new one with the same product > save - Observe that the “Production” Analytic Distribution is not added (although “Home Construction” is) **Current behavior before PR:** - Product analytic distributions are not automatically applied when the Sales Order is already linked to a project **Desired behavior after PR is merged:** - Product analytic distributions are automatically applied even when the Sales Order is linked to a project **Note:** This commit basically ports a fix/revert (https://github.com/odoo/odoo/commit/54852978617cfb2d8c5afdcf80adbf6c0605093c) introduced to the project_purchase module for the same issue. Their commit message is quite detailed in explaining the issue. To quote: >However, due to the agency of the code, we cannot prevent losing *both* manually added analytic distributions and product analytic distribution. After consulting the product owner, we concluded that there was no perfect solution in this case, but we'd rather keep the product analytic distribution, as it is much harder to add it again after its removal. Therefore, this commit reverts the previously mentioned commit, while keeping the refactor it introduced. The referenced initial commit is here: https://github.com/odoo/odoo/commit/3dfa98bd3b9d5ababe3a7548d604e22350023799 Forward-Port-Of: odoo/odoo#274893
When running `ŧest_free_reservation`, it could happen on very rare occasions that both moves would be created at a different second. In such cases, the test would fail. Since we want to test the case with *exact* same dates, we can't use `assertAlmostEqual` which is usually better for dates. Instead, we freeze the time for the duration of the creation / assignation. runbot-944453 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of:
Original PR description
When running `ŧest_free_reservation`, it could happen on very rare occasions that both moves would be created at a different second. In such cases, the test would fail. Since we want to test the case with *exact* same dates, we can't use `assertAlmostEqual` which is usually better for dates. Instead, we freeze the time for the duration of the creation / assignation. runbot-944453 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#279565 Forward-Port-Of: odoo/odoo#278103
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were written with a trailing comma inside the XML id, making the two checks silently fail for everyone. Only the accounting read group check, written correctly, was effective. Steps to reproduce: - create a service product with "Create on Order: Project & Task", sell it on a sale order and confirm it
Original PR description
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were…
Before this commit, the down payments line of the project profitability panel had no drill down action for salespersons and billing users without accounting access, because the group references were written with a trailing comma inside the XML id, making the two checks silently fail for everyone. Only the accounting read group check, written correctly, was effective. Steps to reproduce: - create a service product with "Create on Order: Project & Task", sell it on a sale order and confirm it - create a down payment invoice from the sale order and post it - create a user with Sales "User: All Documents" access, Project "User" access and no accounting access - as that user, open the dashboard of the generated project and look at the Down Payments line of the profitability panel The Down Payments amount is displayed as plain text, while a user with accounting access can click it to open the related invoices, as intended for the salesperson too. Solution: Move the commas out of the group references. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278521
Miscellaneous changes
This is in preparation for forcefully recommending the use of `execute_query` and `SQL` as early as 19.0. While `execute_query` is the primary recommendation, `execute(SQL(...))` is an OK alternative, but static checking limitations mean queries constructed in function calls, or callers (that includes the implementation of `execute_query` itself), or using conditionals, will be flagged. In that case the easiest pattern is execute(SQL("%s", query)) which we do not want to penalize overl
Original PR description
This is in preparation for forcefully recommending the use of `execute_query` and `SQL` as early as 19.0. While `execute_query` is the primary recommendation, `execute(SQL(...))` is an OK alternative, but static checking limitations mean queries constructed in function calls, or callers (that includes the implementation of `execute_query` itself), or using conditionals, will be flagged. In that case the easiest pattern is
execute(SQL("%s", query))
which we do not want to penalize overly.
- Add fast path for `SQL("%s", arg: SQL)`.
- Improve fast-path for `SQL(SQL())` to do ~nothing when possible.
- Allow overriding `to_flush` in both case, fix site which needs that
- Update type dispatches to check for `Iterable` instead of `__iter__`. this both helps type checkers and is actually correct.
Forward-Port-Of: odoo/odoo#2589306 changes
Resolved issues and error corrections
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots & Serial Numbers in Settings. - Create two products: Car and Engine. - Configure Engine to use Unique Serial Number tracking (Inventory →Traceability). - Set the on-hand quantity of Engine to 1 with serial number 0001. - Create a BoM for Car using Engine as a component. - Create and confirm a man
Original PR description
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots &…
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots & Serial Numbers in Settings. - Create two products: Car and Engine. - Configure Engine to use Unique Serial Number tracking (Inventory →Traceability). - Set the on-hand quantity of Engine to 1 with serial number 0001. - Create a BoM for Car using Engine as a component. - Create and confirm a manufacturing order for Car. - Click `Consumed` for the component and click Produce All. - Navigate to Lots & Serial Numbers → Engine → 0001 → Traceability. - Click the arrow next to the manufacturing order reference, then click Print. ## Observed Behavior: An `Arbitrary Uncaught Python Exception` traceback is raised, resulting in a 404 error. ## Root Cause: This issue occurs because, when the user clicks the arrow button in the traceability report, the template [1] invokes the `onClickUpDownStream` function. This function adds the URL `/stock/output_format/stock/active_id` to the context , as shown in [2]. Later, when the user clicks the Print button, `onClickPrint()` [3] constructs the print URL using the `controllerUrl` value by replacing the active model and active ID placeholders with values from the context. However, the URL stored in the context contains `/active_id` instead of `:active_id`. As a result, the placeholder replacement does not occur, leaving the URL unchanged. This causes the print action to use an invalid URL, ultimately resulting in a 404 error. As shown in [4], `controllerUrl` is assigned directly from the context. [1]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.xml#L52-L56 [2]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L105-L118 [3]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L120-L131 [4]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L53-L55 ## Solution: Pass the correct URL in the context so that the active ID placeholder can be replaced correctly during the print action. This ensures that the generated print URL is valid, allowing the user to print the report without encountering any errors. opw-6372834 Forward-Port-Of: odoo/odoo#276449
**Summary**: When a user receives products from a Purchase Order and later decreases the ordered quantity below the quantity already received, Odoo currently allows the change to be saved. This leaves the Purchase Order in an inconsistent state, where the received quantity exceeds the ordered quantity. **Steps to reproduce:** - Install the Purchase and Inventory modules. - Create a Purchase Order with one storable product. - Set the ordered quantity to 10. - Confirm the Purchase Order.
Original PR description
**Summary**: When a user receives products from a Purchase Order and later decreases the ordered quantity below the quantity already received, Odoo currently allows the change to be saved. This…
**Summary**: When a user receives products from a Purchase Order and later decreases the ordered quantity below the quantity already received, Odoo currently allows the change to be saved. This leaves the Purchase Order in an inconsistent state, where the received quantity exceeds the ordered quantity. **Steps to reproduce:** - Install the Purchase and Inventory modules. - Create a Purchase Order with one storable product. - Set the ordered quantity to 10. - Confirm the Purchase Order. - Receive all 10 units and validate the receipt. - Return to the Purchase Order. - Change the ordered quantity from 10 to 5. - Save the Purchase Order. **Observed Behavior:** The Purchase Order is saved successfully even though only 5 units are ordered while 10 units have already been received. This results in an inconsistent state because the ordered quantity becomes lower than the quantity already received, breaking the expected business logic and potentially leading to inconsistencies between purchase and stock data. **Previous behavior:** Until v18.0, Odoo prevented users from decreasing the ordered quantity below the quantity already received by raising a validation error. Starting from v18.3, following the introduction of the new purchase quantity update flow (see PR #209110), this validation is no longer applied when updating the ordered quantity, allowing the Purchase Order to be saved in an inconsistent state. **Cause:** The new purchase quantity update flow introduced in v18.3 updates the Purchase Order line without validating that the new ordered quantity remains greater than or equal to the quantity already received. As a result, decreasing the ordered quantity below `qty_received` is accepted, creating an inconsistent Purchase Order where the received quantity exceeds the ordered quantity. This regression was introduced because the validation present in the previous flow is no longer enforced in the new update flow. **Fix:** Restore the missing validation in the new purchase quantity update flow to prevent decreasing the ordered quantity below the already received quantity. If a user attempts to do so, raise a `UserError` instructing them to create a return before reducing the ordered quantity. opw-[6270228](https://www.odoo.com/odoo/project/49/tasks/6270228)
Issue: Compare to lot and serial number package are not multi company. It means that the package don't pass from a company to the other. So when a company deliver to another. The delivery will create a quant with the package. However the receipt in the other company will create a new quant without package (or a new package). It means that the quants are never reconcile and it could become difficult to understand what remains in intercompany location and what are artifact from past movements.
Original PR description
Issue: Compare to lot and serial number package are not multi company. It means that the package don't pass from a company to the other. So when a company deliver to another. The delivery will create a quant with the package. However the receipt in the other company will create a new quant without package (or a new package). It means that the quants are never reconcile and it could become difficult to understand what remains in intercompany location and what are artifact from past movements. In order to fix it, we introduce a new system parameter to directly unpack after the delivery. This way the receipt is always without source package and will automatically decrease the quant. opw-6376983 Forward-Port-Of: odoo/odoo#277133
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ##
Original PR description
### Steps to reproduce the issue: 1. Download Accounting and l10n_de 2. Set VAT number for DE company and another company you will use for the invoice 3. Switch to german language 4. Create an invoice and send it 5. Download the PDF and upload it on www.portinvoice.com 6. See the following error: the PDF metadata incorrectly states the conformance level as "ERWEITERT" (German), which directly clashes with the correct "EXTENDED" (English) profile declared inside the embedded XML file. ### Cause of the issue: Issue comes from this commit 9396790e9cc1ce1c6e5c29b71b5629b31fb16458 where it has been forgotten to disable the translation. ### Reason to introduce the fix: Meet the requirements of the electronic invoice. opw-6023971 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#273042
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day column right after the transition gets the wrong weekday name, duplicating the previous day's name. For ex. it renders "... THU THU FRI ..." instead of "... THU FRI SAT ...", for the week surrounding April 30th 2027. To fix this we add 1 hour to the Date before reading its weekday/day from it, mirrori
Original PR description
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day…
Current behaviour: In the Calendar view (day/week/month scale), when the user's timezone observes a DST transition that starts exactly at local midnight (e.g. Africa/Cairo, since 2023), the day column right after the transition gets the wrong weekday name, duplicating the previous day's name. For ex. it renders "... THU THU FRI ..." instead of "... THU FRI SAT ...", for the week surrounding April 30th 2027. To fix this we add 1 hour to the Date before reading its weekday/day from it, mirroring the workaround FullCalendar itself adopted for this same bug. It has no effect on any ordinary day (adding 1h to a correct local midnight stays within the same calendar day), and it cannot overshoot into the next day since no real-world DST gap exceeds that margin. Note: This is a known bug (https://github.com/fullcalendar/fullcalendar/issues/7633), fixed in FullCalendar v6.1.17, a major version ahead of the v4.4.0, so the fix can't be applied directly without a full library upgrade. opw-6370140 Forward-Port-Of: odoo/odoo#279836 Forward-Port-Of: odoo/odoo#279343
**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution is not automatically applied to the order line. This occurs due to a previous commit that attempted to protect manually entered analytic distributions from being overwritten when an SO is confirmed and a project is generated. To do this, the old code filtered out any non-empty project lines and
Original PR description
**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution…
**Description of the issue/feature this PR addresses:** When adding a product with an analytic distribution to a Sales Order that is already linked to a project, the product's analytic distribution is not automatically applied to the order line. This occurs due to a previous commit that attempted to protect manually entered analytic distributions from being overwritten when an SO is confirmed and a project is generated. To do this, the old code filtered out any non-empty project lines and bypassed calling `super()` on them. Consequently, if a line already had an analytic distribution (such as inheriting the project's), the system would skip computing the product's specific distribution rules entirely. This commit resolves the issue by reverting that change, ensuring the base compute method is always called so product-based rules execute correctly. While this means manual analytic entries added before the compute trigger might be overwritten, there is no perfect solution to prevent losing both manual and product distributions. As concluded with the Product Owner in a similar PR for Purchase Orders, we prioritize keeping the product's automated distribution, as it is much harder to manually reconstruct after its removal. The corresponding test is also reverted to its original state to reflect this expected behavior. A small test is added to ensure that the analytic distribution results are unchanged when adding a project to the SO. opw-6279406 **Steps to Reproduce:** - Accounting > Configuration > Settings > Analytics > enable Analytic Accounting - Accounting > Configuration > Analytic Accounting > Analytic Distribution Models - Create a new model with any product (e.g. “Bolt”) and any Analytic Distribution (e.g. “Production”) - Create SO, enable “Analytic Distribution” in filters - Add any customer, add the above product (e.g. “Bolt”), save - Observe that the “Production” Analytic Distribution is automatically populated - On the same SO > Other Info> Project > add (e.g. “Home Construction”) - Then go back to Order Lines and remove the previous SOL and create a new one with the same product > save - Observe that the “Production” Analytic Distribution is not added (although “Home Construction” is) **Current behavior before PR:** - Product analytic distributions are not automatically applied when the Sales Order is already linked to a project **Desired behavior after PR is merged:** - Product analytic distributions are automatically applied even when the Sales Order is linked to a project **Note:** This commit basically ports a fix/revert (https://github.com/odoo/odoo/commit/54852978617cfb2d8c5afdcf80adbf6c0605093c) introduced to the project_purchase module for the same issue. Their commit message is quite detailed in explaining the issue. To quote: >However, due to the agency of the code, we cannot prevent losing *both* manually added analytic distributions and product analytic distribution. After consulting the product owner, we concluded that there was no perfect solution in this case, but we'd rather keep the product analytic distribution, as it is much harder to add it again after its removal. Therefore, this commit reverts the previously mentioned commit, while keeping the refactor it introduced. The referenced initial commit is here: https://github.com/odoo/odoo/commit/3dfa98bd3b9d5ababe3a7548d604e22350023799 Forward-Port-Of: odoo/odoo#274893
39 changes
Security fixes and vulnerability patches
Employee payroll fields for Swiss, Indonesian, and Turkish payroll are now only accessible to authorized payroll users. This helps protect sensitive payroll information and prevents non-payroll staff from seeing or using these fields.
Original PR description
This commit adds `groups="hr_payroll.group_hr_payroll_user"` to all fields displayed inside payroll tab in the form view of employee to make sure those fields are only accessible to payroll users. runbot-error-234071 Forward-Port-Of: odoo/enterprise#124880 Forward-Port-Of: odoo/enterprise#122293
New functionality added to Odoo
Indian payroll users can now choose ENet as a payment export format and generate the required CSV file from the payroll payment wizard. This makes it easier to prepare salary payment files for banks or payment workflows that use ENet.
Original PR description
This PR adds: - a new `export_format` option as "ENet", and its payment methods - if "ENet" is selected, you can generate ENet CSV using the wizard Task-4585620
The Japanese reporting module now includes statutory Balance Sheet and Profit & Loss statements tailored to local presentation requirements. This helps businesses in Japan prepare required financial reports more directly from their existing chart of accounts setup.
Original PR description
Add the Japanese statutory financial statements (Balance Sheet and Profit & Loss), laid out to the local presentation and driven by the account types and tags from the chart of accounts. task-6271211
Enhancements to existing features
This update makes Odoo's AI assistant more flexible by standardizing how browser-side actions are handled and how results are returned to the AI. It also improves user experience by updating AI thinking messages more dynamically, preserving normal view filters when opening records, and preventing new messages while the assistant is still responding.
Original PR description
Purpose: -------- Instead of handling each AI client tool as a special case when posting a message in the thread, a dedicated registry (ai.client_tools) has been added to make it easy to declare and…
Purpose:
--------
Instead of handling each AI client tool as a special case when posting a message in the thread, a dedicated registry (ai.client_tools) has been added to make it easy to declare and extend client-side tool handlers: `registry.category("ai.client_tools").add(name, (thread, params) => cb);`
On the Python side, AI tools can now trigger client-side behavior by returning a "client_tool" entry with a name and params, keeping the server interface minimal and consistent.
Updating the thinking text is now done using one of this tool, allowing to update the thinking text more dynamically. For example, the thought will now be updated when the web search tool has been executed.
Also, with this commit, the action domains are not overridden anymore: before, if you asked to open your crm pipeline, it would open it without the default hidden domain (type = 'opportunity'). Now, this domain will be applied, so that the view opened is the same as if the user opened it manually.
#### Async JS tools
Client tools can now pause the agent loop, return a result from the
browser and resume the conversation with this result.
By default, client tools wait for a result from the browser. Tools that
do not need to return a result can set `oneway` to true, allowing the
agent loop to continue without creating a pending tool call (for example
to show a notification).
Tool confirmations and client tool results use the same pending tool
response flow. Confirming a tool re-executes it on the Python side,
while returning a client tool result resumes the loop without
re-executing the tool.
To add a tool that allows the agent to get a result from the browser,
one needs to:
- add an AI tool in the backend that returns a dict with a `client_tool`
entry: `'client_tool': {'name': name, 'params': {}}`;
- add an AI tool in the frontend with the same name in the
`ai.client_tools` registry and return the result that needs to be sent
to the LLM.
For a client tool that does not need to return a result, use the `'oneway'`
option on the `client_tool` entry:
`'client_tool': {'name': name, 'params': {}, 'oneway': True}`
To prevent race conditions that could happen when the user sends a new
message while a client tool is being processed, the send button will now
be disabled when the agent is generating a response.
This commit also removes references to `ai_session_identifier` which was
not used anymore.
Task-6352942Improves the process that suggests reconciliation rules when assigning accounts to bank statement lines. The change prevents failures and slowdowns caused by very long payment references, making bank reconciliation setup more reliable for accounting users.
Original PR description
When setting an account to an account.bank.statement there is a step to automatically create a reconciliation rule/model if one does not exist already. To do so, we retrieve 5…
When setting an account to an account.bank.statement there is a step to automatically create a reconciliation rule/model if one does not exist already. To do so, we retrieve 5 account.bank.statement.lines and use them to define the reconciliation model config. A matching is done on the payment_ref of the account.bank.statement.lines by finding the longest common substring in the reference. ### Current Implementation The current algorithm does so by first generating all the possible substrings for all the payment_ref before doing the intersection between these sets and returning the max if `len(substring) >=10`. This is reasonable when the payment_ref follows either a SEPA communication national standard like the Belgian one or the Creditor Reference standard (ISO 11649). For transactions with large, unstructured communication with more than 100 chars, the method `_get_common_substrings` quickly overfill the memory, sometimes raising a MemoryErorr, and takes a significant amount of time. That's because the nested function `_generate_all_substrings` generates n*(n+1)/2 substrings, with n being the lenght of a payment_ref, called `label` in `generate_all_substrings`. ### Proposed Fix This commit introduces another algorithm to find the largest common substring. It starts by taking the two smallest labels to find their substrings intersection. We know that for an arbitrary collection of labels, the intersection of their substrings sets A ∩ B ∩...∩ Z is included in the intersection of any two substrings sets. The underlying assumption of the first step is that for an arbitrary collection of labels the intersection of the substrings sets of the two smallest labels will be the smallest intersection of any given pair of substrings sets. This won't hold true everytime and using a metric such as label similarity instead of shortest string might be better. But on average this should be good enough and it's easier to implement + it removes the need of preprocessing the labels to compute the similarity. The point of the new nested function `common_substrings` is to discard common substrings as we build them. Using the current `generate_all_substsrings` on either the smallest label or both smallest labels would still generate and store a lot of substrings, especially for large labels. By yielding the common substrings as we find them, the memory footprint is vastly reduced. Lastly, the next substring in the common_substrings iterable is only checked against the remaining labels if it's longer than the current match. This speeds up the whole process ### speedup In a customer database with some account.bank.statement.line with payment_ref > 500 chars, setting a specific account (code 4970) on transactions goes from MemoryError to < 1Mb memory consumption. Because of the memory consumption it was not possible to gather timing value on the current version. Testing the new algorithm in a shell and using as labels the 5 longest payment_ref in the customer database (831, 831, 1117, 1178, 1300 chars), averaging to 2000 chars once normalised, the average time to execute `_get_common_substrings` is 900 ms ± 10.3 ms. Forward-Port-Of: odoo/enterprise#121575 Forward-Port-Of: odoo/enterprise#118824
The website builder now shows a proper preview image for the AI live chat snippet, even when live chat is not installed. Users can also preview the fallback contact button on hover, making the editing experience clearer and more consistent.
Original PR description
*:ai_website_livechat Problems: 1) There's no preview of the livechat snippet in the website builder. If ai_website is installed but not livechat, there's no preview image for the snippet resulting in a cluttered and inconsistent UX. 2) There is no preview on hover for the livechat preview button. Unlike other odoo builder options, the user cannot see what the livechat preview button would look like if hovered over. Solutions: 1) An image has been added `ai_livechat.png` which is shown on preview 2) The AI livechat fallback is previewable and defaults to "Contact Us" linking to the /contactus page. Task-5248712
The timesheet ActivityWatch suggestions panel now displays total tracked time by project and an overall total at the bottom. This gives users a clearer view of how much time has been captured before creating or reviewing timesheets.
Original PR description
This commit introduces new time tracking metrics to the ActivityWatch suggestions panel to improve user visibility into their tracked hours. **Enhancements:** - Added the total duration per project in the By Project grouped view. - Added a grand total footer for all suggestions at the bottom of the list. task-6088877 Forward-Port-Of: odoo/enterprise#125515 Forward-Port-Of: odoo/enterprise#114772
This update aligns several country-specific Point of Sale accounting and electronic invoicing flows with recent accounting changes. It helps keep POS receipts, fiscal certification, and tax reporting working correctly across affected localizations after the accounting refactor.
Original PR description
Refector PR: https://github.com/odoo/enterprise/pull/112634
Shop floor users can now manually adjust production time logs when a timer was not started or stopped correctly. This helps keep work order timing accurate by creating or closing time entries based on the corrected time.
Original PR description
The "Update Time Log" dialog inside shopfloor is added to increase the timer's reliability by manually entering the desired time. If someone forgot to start the timer, this option adds a new productivity line ending now. If someone forgot to stop it, this option close the timer and set the end date accordingly. Task-6164336
When an item quantity is set to zero in the certified Point of Sale flow, all removed order lines are now visibly struck through, not just weighted products. This improves receipt and order clarity and prevents newly added items from being incorrectly merged with previously removed lines.
Original PR description
We now strike every orderline instead of only the ones related to weightable products, when quantity is set to 0. We also fix an issue where the PoS kept merging new orderlines with strikedthrough ones. task-6425588
Cashiers can now see each customer's due or deposit amount directly on the mobile customer selection card. This makes it easier to spot outstanding balances or available deposits before choosing a customer, speeding up checkout decisions.
Original PR description
This commit adds the customer's due/deposit amount to the customer card displayed in the mobile customer selection list, allowing cashiers to quickly identify outstanding balances or available deposits when choosing a customer. Task-6329233 Related PR: https://github.com/odoo/odoo/pull/272076 <img width="200" height="431" alt="image" src="https://github.com/user-attachments/assets/d4ad9e0a-34f9-4995-84d3-8c28058cba4f" />
This updates internal tests for the rental website planning feature to match recent Google Analytics 4 tracking behavior. It helps keep automated checks reliable when analytics tracking is enabled, with no expected change for day-to-day users.
Original PR description
`tracking_info` is now only computed when `google_analytics_key` is set, and `item_id` now uses the template id as a string rather than the variant id as an integer. Set the key in `setUpClass` and update assertions accordingly. See : - https://github.com/odoo/odoo/pull/253856
The manufacturing work order display was slightly simplified by moving an internal setting to the main screen component instead of sharing it more broadly. This reduces unnecessary internal complexity without changing how users interact with the feature.
Original PR description
This commit removes localStorageName from env. It was added in the env but never used in child components so it can be set on the root component.
HR users can now complete employee document signature requests themselves when they are the only required signer. This removes the unnecessary step of sending the document to the employee, saving time and simplifying the process.
Original PR description
Before:
- When creating a Signature Request from the employee form:
- If the document had only one signer (HR user), the system still asked to
send it to the employee.
- HR users could not sign the document directly.
After:
- If there is only one signer (the HR user):
- The HR user can now sign the document directly.
- No need to send the document to the employee.
Impact:
- Saves time for HR users.
- Makes the process simpler and faster.
- Reduces unnecessary steps.
Task: 6032364Resolved issues and error corrections
Restored automated checks for online payment flows in self-order and kiosk preparation display scenarios. This helps ensure payment journeys continue to work correctly and reduces the risk of regressions reaching customers.
Original PR description
The four online payment preparation display tests were skipped because their tour never reached the online payment step. - Register the tour, and the `pos_self_order` tour utils it imports, in `web.assets_tests`. The tour leaves the self-order SPA for the `/pos/pay/<id>` payment portal page, where only the frontend bundle is loaded, so without this the tour is gone from the registry as soon as the page is unloaded. - Make the "Pay" step use `expectUnloadPage: true` and wait for the payment portal submit button, so the tour actually reaches the payment page instead of ending on the self-order page. - Use the `test_online_payment_kiosk_qr_code` tour for the two kiosk tests, which stay in the kiosk and check the QR code. - Unskip the four tests and move their duplicated setup into a kiosk and a self-order helper. task-id: 6244255
The Timesheet Assistant no longer suggests calendar events marked as available. This keeps recommendations focused on events that may need timesheet entries and reduces distractions for users.
Original PR description
## Previous Behavior In the Timesheet Assistant view, calendar events marked as *available* were still being suggested. These events are not intended to be timesheeted and should not appear in the assistant’s recommendations. Their presence could also obscure more relevant events that require user attention. ## New Expected Behavior Calendar events marked as *available* are now excluded from Timesheet Assistant suggestions. task-[6431591](https://www.odoo.com/odoo/project/4105/tasks/6431591) Forward-Port-Of: odoo/enterprise#126183
The expense Stripe cardholder field now uses the standard setup for selection fields, ensuring filters defined in the view are applied correctly. This prevents users from seeing or choosing inappropriate cardholder records when managing expense card details.
Original PR description
After https://github.com/odoo/odoo/issues/196785; the standard way to build a custom m2o field in JS is to call a method from the Many2one module, instead of extending an object from it. This commit solves issues regarding domain in the view not being passed to the widget opw-6399906 Forward-Port-Of: odoo/enterprise#125346
This change corrects how Timesheet Grid recognizes Discuss-related rules so notification count badges do not interfere with matching. It helps ensure the intended automation or guidance continues to work reliably when users have unread notifications.
Original PR description
task: 6416889 Forward-Port-Of: odoo/enterprise#125877 Forward-Port-Of: odoo/enterprise#125519
The Field Service planning map now checks assignments more reliably before showing the routing popup. This prevents errors when planning groups contain unassigned work or translated labels, improving stability for schedulers.
Original PR description
This commit fixes an issue where we search the resources' types in a group's records, possibly not having any resource. Prior to this commit, a condition filtered out the "None" group. However, this causes three issues: 1. The condition does not consider translations (so this would fail for the "None" group in French for instance); 2. If there is any other group than Open Shifts not having resources, this would fail. 3. If there is another group that does not belong to a resource or to Open Shifts that has some records without resources, we should not display the popup. Instead, we dynamically check whether the groupId is part of the resource_ids of *every* group's record in order to display the popup. no-task Forward-Port-Of: odoo/enterprise#126394
Users can now adjust the start or end time of scheduled work orders directly in the Gantt view without triggering an error. The fix also improves handling of dependent work orders, so related scheduling changes continue smoothly instead of failing when a linked item is being moved.
Original PR description
## Problem When dragging the edge of a scheduled workorder to change the start or end time, _web_gantt_move_candidates would throw a traceback. This is because the web call only supplies the new time…
## Problem When dragging the edge of a scheduled workorder to change the start or end time, _web_gantt_move_candidates would throw a traceback. This is because the web call only supplies the new time chosen by the drag+drop. That is, if date_end was changed, date_start wouldn't be present, so accessing the missing field directly triggers a KeyError. This also revealed a secondary issue involving dependent tasks, where if the parent task is rescheduled with the pills, the child task would fail to find candidate reschedule dates (since its only dependency is being moved), and no boundary date would be supplied when calling _web_gantt_reschedule_compute_dates. This led to another traceback. ## Solution For the first issue, we will get the start date and end date from the supplied values more safely, using get() to default to the original start/end. For the second issue, if the boundary date isn't found by _web_gantt_get_first_and_last_possible_dates, we fall back to the candidate's existing start or end date. ## Steps to replicate (Runbot saas-19.4) 1. Create a product with a BOM with 2 operations on the same workcenter 2. Create an MO for this product, confirm it, and plan it 3. Head to Manufacturing > Planning > Work Orders / Planning 4. Try to change the end date of the first work order by dragging the edge of the pill opw-6378769 Forward-Port-Of: odoo/enterprise#124710
The printer selection popup now correctly limits choices to printers assigned for the report. This helps users choose the right printer and avoids accidental printing to unrelated devices.
Original PR description
This commit fixes the domain for the printer selection popup when printing a report. The assigned printers were not taken into account. task-6332442 Forward-Port-Of: odoo/enterprise#122404
The timesheet assistant now keeps its suggestions aligned with the date the user most recently selected, even when switching dates quickly. This prevents outdated suggestions from another day appearing due to delayed background requests.
Original PR description
Before this commit, when the user hits multiple times the arrow button to change the date displayed in timesheet assistant, the suggestions displayed could be the suggestions from another day because a rpc is made each time the user changes the date and amoung all rpcs call, the one which takes more time then the one will be taken but it is not necessary the date shown in the view. This commit uses `KeepLast` class to avoid the concurrency issue with those rpcs to be able to always take the last rpc call to get the data. Forward-Port-Of: odoo/enterprise#126323 Forward-Port-Of: odoo/enterprise#126283
Guatemalan electronic invoice PDFs now match the tax information used in the official XML file. This prevents mismatches when customer tax IDs are missing or placeholder values are used, and applies the legal threshold consistently across currencies.
Original PR description
with this commit:- - Display 'CF' in the invoice PDF whenever the generated XML uses CF. - Treat placeholder VAT values such as '/', 'NA', and 'na' as missing VAT. - Compare the invoice total using the company currency instead of the document currency when evaluating the 2,500 threshold, ensuring the legal limit is applied consistently regardless of the invoice currency task-6305333 Forward-Port-Of: odoo/enterprise#120985
This fix lets regular invoicing users post invoices or reset them to draft when Avalara tax integration is enabled. It removes an access-related blocker so day-to-day invoice processing does not require administrator intervention.
Original PR description
The field `avalara_connection_method` has a restriction to only admins, but needs to be read by normal invoicing users in order to post or reset invoices to draft. Forward-Port-Of: odoo/enterprise#126464
This fix prevents an error when creating a Hong Kong payslip for an employee whose contract start date is missing. Payroll users can now select the employee and continue payslip preparation without the system crashing, while existing handling for missing dates remains in place.
Original PR description
Currently, an error occurs when a user sets an employee on a payslip. **Steps to Reproduce:** - Install `l10n_hk_hr_payroll` with demo data. - Switch to the `Hong Kong` company. - Create an…
Currently, an error occurs when a user sets an employee on a payslip. **Steps to Reproduce:** - Install `l10n_hk_hr_payroll` with demo data. - Switch to the `Hong Kong` company. - Create an `employee` and make sure that the employee's version has no `contract start date`. - Go to `Payroll` > `Payslips` > `Payslips`. - Create a `payslip` and set that employee. `TypeError: '<' not supported between instances of 'datetime.date' and 'bool'` When a user sets an employee on a payslip, the system computes the worked day lines [1]. If the salary structure uses worked day lines, it creates the corresponding records [2] and calculates out days and out hours based on the contract dates. During this process, the payslip dates are compared with the version's contract start date. If the version does not have a contract start date, it raises an error [3]. This commit ensures that the payslip dates are compared with the version's contract start date, and that out days and out hours are calculated only when the contract start date exists. Cases where no contract start date is defined are already handled in payslip [4]. [1]: https://github.com/odoo/enterprise/blob/03787659236cbcb46c27acebf410ee3d1e9eb15c/hr_payroll/models/hr_payslip.py#L1964 [2]: https://github.com/odoo/enterprise/blob/03787659236cbcb46c27acebf410ee3d1e9eb15c/hr_payroll/models/hr_payslip.py#L1985-L1988 [3]- https://github.com/odoo/enterprise/blob/03787659236cbcb46c27acebf410ee3d1e9eb15c/l10n_hk_hr_payroll/models/hr_payslip.py#L309 [4]- https://github.com/odoo/enterprise/blob/03787659236cbcb46c27acebf410ee3d1e9eb15c/hr_payroll/models/hr_payslip.py#L1092-L1096 sentry-7632216317 Forward-Port-Of: odoo/enterprise#120234
Quotations created from repair orders linked to helpdesk tickets now automatically use the salesperson assigned to the customer. This prevents missing salesperson information, helping sales ownership and follow-up stay accurate.
Original PR description
Currently, when a quotation is created from a repair order generated from a helpdesk ticket, the salesperson is not set on the quotation even if the customer has a salesperson assigned. **Steps to…
Currently, when a quotation is created from a repair order generated from a helpdesk ticket, the salesperson is not set on the quotation even if the customer has a salesperson assigned. **Steps to Reproduce:** - Install `helpdesk_repair`. - Go to `Helpdesk` > `Configuration` > `Helpdesk Teams`. - Open a team recod and enable `Repairs`. - Create a `contact/customer` with a `salesperson` assigned. - Go to `Helpdesk`, create a ticket for that `customer`, and select the `helpdesk team` configured above. - Click `Repair`, then click `Create Quotation`. - Open the quotation and check the `Salesperson` field in the `Other Info` tab. **Current behavior:** The Salesperson field on the quotation remains empty. **Expected behavior:** The Salesperson field on the quotation should inherit the salesperson assigned to the selected customer/contact. **Cause of the issue:** When a repair order is created from a helpdesk ticket, default_user_id [1] is passed in the context . This value is propagated when creating the repair order [2] . Later, when creating the quotation from the repair order [3], the same context is reused. Because default_user_id is already present in the context, it overrides the precomputation of user_id from the customer. As a result, user_id is initialized with an empty value and remains unset. **Fix:** This commit ensures that default_user_id is removed from the context before creating the sale order. Without a default value for user_id, the field is correctly precomputed from the selected customer, and the salesperson is properly assigned. [1]- https://github.com/odoo/enterprise/blob/2662932c7ac8ebf3ed5a05d44d7ebfaff869fcbd/helpdesk_repair/models/helpdesk_ticket.py#L52 [2]- https://github.com/odoo/enterprise/blob/2662932c7ac8ebf3ed5a05d44d7ebfaff869fcbd/helpdesk_repair/models/helpdesk_ticket.py#L36-L40 [3]: https://github.com/odoo/odoo/blob/29328b8fccff833c14de317b51f3b4e5a8c40f75/addons/repair/models/repair.py#L357 opw-6344939 Forward-Port-Of: odoo/enterprise#126310 Forward-Port-Of: odoo/enterprise#122980
The Argentine electronic invoicing test setup was adjusted so a live currency-rate check is not run during daily builds that block external web requests. This prevents avoidable build failures while still allowing the check to run in nightly testing with the right access.
Original PR description
Description of the issue this commit addresses: The live ARCA currency rate test keeps the inherited `standard` tag. It is therefore selected by daily builds whose HTTP guard blocks the request. The guard also blocks it when selected by the external localization suite. --- Desired behavior after this commit is merged: This commit removes the `standard` tag from the live ARCA test. Daily builds skip the test while nightlies still run it with HTTP access. --- runbot-[238857](https://runbot.odoo.com/odoo/error/238857) Forward-Port-Of: odoo/enterprise#125692
Date and date-time fields are now hidden from the column selection popover once they have already been added, just like other fields. This prevents duplicate columns from being created and avoids inconsistent spreadsheet behavior for users configuring list views.
Original PR description
Current behavior before PR: - Date and datetime fields remained visible in the popover after being added as columns, allowing the same field to be added multiple times. - Since column fields do not consider granularity, allowing duplicate date fields could create duplicate IDs and inconsistent behavior. Desired behavior after PR is merged: - Treat date and datetime fields the same as other column fields when determining which fields to display in the popover. - Once a date or datetime field is added as a column, it is no longer shown in the popover to prevent duplicate IDs. Task: [6295794](https://www.odoo.com/odoo/project/2328/tasks/6295794) Forward-Port-Of: odoo/enterprise#123463
Internal CRM users can once again create leads from business card pictures without needing administrator rights. The change keeps access checks for actions tied to specific records while allowing the business card option when the related app is available.
Original PR description
**Steps to reproduce:** - Go to CRM app as an internal user (non-admin) - Click on Generate button - Can't create leads from business card pictures - Only setting the user as admin enables it (was…
**Steps to reproduce:** - Go to CRM app as an internal user (non-admin) - Click on Generate button - Can't create leads from business card pictures - Only setting the user as admin enables it (was working fine in previous versions) **Issue:** Dropdown action is restricted to admin only by default using `hasAccess`. If there is a corresponding model on the `LeadGenerationDropdown` it is later changed according to the current user access rights using `await user.checkAccessRight(model, "create")`. **Fix:** Default `hasAccess` to `True` as there is no related model for the lead generation of business cards. (Note: could also provide the missing model ?) - Installation should be restricted to the admin. - Access message should be shown to the user if he doesn't have enough rights to the related model. - Non-admin users should be able to use the feature if no model is provided and the related app is available. dropdown: https://github.com/odoo/odoo/commit/978019522746ccb971eeb15c5d9530e438b7d2f3 business card: https://github.com/odoo/enterprise/commit/48a9cba24cb51b11a08dd9c0ff1291e15232260f opw-6258689 Forward-Port-Of: odoo/enterprise#121682
Restaurant orders using the German Fiskaly POS certification now show on the Kitchen Display as soon as the first item is added. This prevents kitchen staff from missing or delaying newly created orders in affected German POS setups.
Original PR description
**Step To Reproduce:** 1. Configure a POS with German Fiskaly (l10n_de_pos_cert), Restaurant, and Kitchen Display (pos_preparation_display). 2. Create a new order in the POS and add the first…
**Step To Reproduce:** 1. Configure a POS with German Fiskaly (l10n_de_pos_cert), Restaurant, and Kitchen Display (pos_preparation_display). 2. Create a new order in the POS and add the first product. 3. Observe that the order does not appear on the Kitchen Display. 4. Add a second product to the same order. 5. Observe that the order now appears on the Kitchen Display. **Issue:** The first product of a new restaurant order is not synchronised with the Kitchen Display when the German Fiskaly localisation is enabled. **Reason:** `syncAllOrders()` only processes orders returned by `getPendingOrder()` and ignores orders explicitly passed through `options.orders`. After the initial Fiskaly synchronisation, the order is serialised and removed from the pending queue. Consequently, the Preparation Display synchronisation receives no orders from `getPendingOrder()`, preventing the order from reaching the backend. **Solution:** Update `syncAllOrders()` to prioritize the orders explicitly provided through `options.orders`. When `options.orders` is not available, fall back to the existing behavior by synchronizing the orders from `orderToCreate` and `orderToUpdate`. opw-6321376 Forward-Port-Of: odoo/enterprise#125743
This fix makes automated tests for assigning planning resources more stable by avoiding timing-related selection mistakes. It helps reduce false test failures, supporting smoother validation and delivery of Planning field service changes.
Original PR description
This commit fixes undeterministic failures in the `many2many_avatar_resource` tests. Previously, resources were added by typing its name, waiting for the list to update and clicking on the resource. However, `edit` auto-completes with some delay, thereby resulting in random errors where the first resource from the list was added. Instead, we let the `edit` autocomplete to run in order to add a resource, ensuring the first resource from the list is not added as a consequence. runbot-error-941174 Forward-Port-Of: odoo/enterprise#126482
The Belgian payroll rules for CP302 eco-vouchers have been corrected so employees receive prorated voucher amounts based on the proper treatment of full-time, part-time, partial-year work, public holidays, and unpaid absences. This helps payroll teams apply sector rules more accurately and reduces the risk of incorrect employee benefits.
Original PR description
Per the CP302 rules:
- Full-time, incomplete year: 250 × complete_months/12 + 250 × working_days/divisor for any partial month at start/end.
- Part-time: 250 × working_days/divisor. Days are counted as-is ("each daily service = 1 day regardless of duration"), so work_time_rate is not applied to the day count.
- Divisor: 260 (5-day week) or 312 (6-day week).
- Working days use `get_work_duration_data(compute_leaves=False)` so public holidays stay assimilated; only unpaid absences are deducted.
task-6375105
Forward-Port-Of: odoo/enterprise#126198
Forward-Port-Of: odoo/enterprise#124297Customers can no longer complete checkout for planning-based rental services when the required resources are already booked. This avoids taking payment for rentals that cannot be fulfilled and prompts customers to choose another date or quantity.
Original PR description
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The…
**Problem:** On a website with rental planning enabled, a customer can book a planning-backed rental product through eCommerce even when no planning resource is free for the requested window. The cart lets them increase the quantity past the available capacity and proceed all the way through checkout without any availability gate. **Steps to reproduce:** 1. Install `website_sale_renting_planning`. 2. Create a planning role with `sync_shift_rental` and one resource. 3. Create a service product with `rent_ok=True`, `planning_enabled=True` and the role above. 4. Pre-book the resource for some window via a `planning.slot`. 5. From eCommerce, add the product to the cart for the same window. 6. Proceed to checkout/payment. **Current behavior:** The cart is considered ready, no warning is shown, and payment can proceed even though no planning resource is free for the chosen period. **Expected behavior:** The cart should be flagged as not ready and pre-payment validation should refuse to confirm until the customer picks a different date or quantity. **Cause of the issue:** `sale.order._available_dates_for_renting` in `website_sale_renting` is the documented hook for "stock availability" gating of the cart and pre-payment flow (called from `_is_cart_ready` and from `_check_cart_is_ready_to_be_paid`). `website_sale_stock_renting` overrides it to apply a per-line stock check, but `website_sale_renting_planning` has no such override, so planning-backed rental services reach payment with no availability gate at all. **Fix:** Apply the same gating pattern that `website_sale_stock_renting` already uses: override `_available_dates_for_renting` in `website_sale_renting_planning` so that, for each rental line whose product is a planning-synced rentable service, the cart is only considered valid when at least the requested quantity of planning resources is free during the rental window (mirroring the resource and leave filtering already done by `_planning_slot_vals_list_per_sol` at SO confirmation time). This puts the gate at the same point the stock-renting flow enforces it, keeping the public cart/checkout flow consistent across rentable product types. opw-6247034 Forward-Port-Of: odoo/enterprise#125855 Forward-Port-Of: odoo/enterprise#118943
This fixes how Indian reports classify transaction types for journal entries, especially Point of Sale entries that use general journals. Existing databases are also updated so past entries use the corrected classification logic.
Original PR description
Description: In #118297 non-sales journal moves were considered purchase moves during l10n_in_transaction_type computation, which is not correct for POS moves as their journal is of type 'general'. Fix: Compare only the purchase journal moves state against the partner state. Other moves treated as sales and their state compared against the company state. Add a migration script to update existing databases. opw-638646 Forward-Port-Of: odoo/enterprise#125697
This fix makes Dominican Republic 606 report tests use a consistent document setup instead of depending on which optional modules happen to be installed. It also stabilizes reversal dates, reducing false test failures and helping keep report behavior reliable for customers using either configuration.
Original PR description
Whether DO journals use LATAM fiscal documents depends on `l10n_do_edi` being installed: it is what supplies the `_localization_use_documents` override for DO. l10n_do_reports doesn't depend on it, so the tests inherited whichever configuration the build happened to install, and only went red on the per-module build. Without the EDI module the reversal's `ecf_34` document type produced the name "E34 B0400000001", which the yearly sequence regex reads as year 34; checked against a 2024 date, the sequence constraint rejects it on post. Pin the flag explicitly instead, and run the assertions against both configurations, since customers run both: the NCF is read off the fiscal document number with e-CF, and off the reference without it. Also pin the reversal's accounting date. Left out, `_get_accounting_date` pushes it to the end of the month once the invoice date is in the past, which made the test depend on the date it ran. runbot-error-944488
Accounting report snapshots now store the correct cutoff date for lines that look back to the start of a period or fiscal year. This prevents reports such as balance sheets from silently omitting transactions after a company lock date, improving accuracy for previously affected financial reports.
Original PR description
Once a lock date is set on a company, report lines that look back before a given date, such as a Balance Sheet's "Profits (Losses) from Previous Years", could silently lose data. Any line that gets…
Once a lock date is set on a company, report lines that look back before a given date, such as a Balance Sheet's "Profits (Losses) from Previous Years", could silently lose data. Any line that gets captured in a snapshot and uses a date scope 'to_beginning_of_*' was affected. Snapshots are computed on the options of the lock date and stored with their 'date' set to the options' date_to (the lock date). Only 'from_beginning' actually evaluates the accounting up to date_to. The 'to_beginning_of_*' scopes stop right before the period or fiscal year, so the data really aggregated stops earlier than the stored date: - 'to_beginning_of_fiscalyear': up to a whole fiscal year earlier. - 'to_beginning_of_period': up to a whole period earlier. When the report is rendered, the engine sums only the moves dated after the snapshot's date and adds the snapshot's data. Everything between the snapshot's real cut-off and its (later) stored date is never counted. Aim the options at the lock date so each scope's bound falls on it, and store the date really covered(using _get_date_bounds_info()). The snapshot's date then always matches its data, and "to_beginning_of_*" covers the last fiscal year starting before the lock date instead of forcing every later render to rescan it. Snapshots written before this fix still hold the mismatched date, so the account_codes sub-engine version is bumped to 2 to re-trigger the snapshots generation opw-6379956 Forward-Port-Of: odoo/enterprise#126542
Code cleanup and technical improvements
The VOIP audio manager now tracks changes to call and audio settings in a cleaner way, ensuring observers are properly cleaned up when no longer needed. This reduces the risk of hidden background work building up over time without changing the user-facing calling experience.
Original PR description
Enterprise counterpart of "[REF] mail: drop the onChange queue for owl effects", which explains the API. Before this commit, the audio manager observes three fields by name and drops the dispose function each observer returns, so nothing ever stops those observers. This commit turns the three observers into dependency lists on the rtc and settings records, keeping `initialRun: false`: the refresh at the end of setup does the initial sync. The records dispose these observers. The audio manager tests take the real store: a fake store has no record to observe. One of them counted the calls to `enumerateDevices` to know that the status was refreshed, and with the real store there are two audio managers, the one of the voip service and the one the test builds, both enumerating the devices. That test counts the refreshes of its own manager instead. https://github.com/odoo/odoo/pull/279818
This update renames internal enrollment-related campaign fields to make their purpose clearer and easier to maintain. It also adds safeguards around the enrollment uniqueness field so future campaign setup is more reliable, with no intended change to user-facing behavior.
Original PR description
In order to ease understanding, prepare future changes and ease grep through code, rename enroll-specific fields on campaign model * domain -> enroll_domain * unique_field_id -> enroll_unique_field_id No functional change should come with this PR. Task- Prepares Task-
VoIP configuration such as credentials, device number, and do-not-disturb timing is now read from the dedicated user settings record instead of a mixed local settings area. This aligns VoIP with the newer settings structure, making preferences clearer and easier to maintain without changing the visible user experience.
Original PR description
Before this commit, the voip columns of res.users.settings were read off store.settings, the record that mixed the server row with the local preferences of the device. Reminder that the mail counterpart of this commit splits the two: res.users.settings becomes a record of its own, reached from its owner, store.self_user.res_users_settings_id, and store.settings keeps only the local preferences. This commit declares the voip columns on that record, sends them through _store_settings_fields, and reads a credential, the device number and the do-not-disturb time off it. Note that the field declarations sit in core/common, reachable from every bundle, while the behavior stays in core/web. https://github.com/odoo/odoo/pull/279128
5 changes
Enhancements to existing features
This update adds and improves automated checks for marketing automation flows, especially around failed or bounced messages and scheduled synchronization. It helps reduce the risk of regressions in campaign enrollment and message handling, improving confidence that automated campaigns continue to behave correctly.
Original PR description
Backport various tests added in Odoo 19.4+ in order to better spot potential regressions. Add new tests for synchronization cron behavior, notably in case of failure.
Resolved issues and error corrections
The change updates cash basis accounting report tests so they use the account configured in the system instead of assuming a fixed account code. This prevents false test failures when account codes differ between database setups, improving release validation reliability.
Original PR description
Description of the issue this commit addresses: Commit 63f5646cfd75 made the tests use the default outstanding account but hard-coded code 101403. In an all-module database, generated account codes depend on existing accounts, so Outstanding Receipts may use code 101404 and make otherwise correct report assertions fail. --- Desired behavior after this commit is merged: This commit derives the expected report line name from the configured outstanding receipts account, making the assertions independent of its generated code. --- runbot-[231581](https://runbot.odoo.com/odoo/error/231581)
Employee unavailable time is now calculated consistently across Attendance and Time Off planning views. Days outside an employee contract, including employees without contracts, are clearly shown as unavailable, while flexible schedules are handled more accurately.
Original PR description
…ty of employees purpose: 1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out…
…ty of employees
purpose:
1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out of contract days, flexible and fully flexibe employees. 2- In time off calendar view, if the employee does not have a contract at all, the current working schedule will appear in the calendar and it will not be greyed out. This is inconsistent with the behavior of the attendance application.
Fix:
1:
- implemented `_get_employee_unavailable_intervals` in employee model to be used in both time off and attendance.
- more optimized than the old implementation in time off as it calls `_work_intervals_batch` once per calendar instead of calling it for each contract in `_unavailable_intervals_batch`
- greys out "out of contract" periods
- for flexible and fully flexible employees, the whole period is considered available except leave periods
- made `_get_calendar_periods` use version date start instead of contract date start and corrected a bug in tz conversion 2:
- made `_get_unusual_days` return True for all the days outside of contracts for the employee instead of not returning anything for them or getting values from the working schedule of the employee (means that they will be greyed out in the callendar view) and added a test for it
task-id: 5473055Customer balances in Point of Sale now show the correct Total Due when the company currency differs from the PoS currency. This prevents Pay Later amounts from being converted twice, so staff see the expected customer debt amount.
Original PR description
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any…
Steps to reproduce: - set the company currency to XCG - set the PoS sales journal currency and the PoS pricelist currency to USD - configure a XCG <-> USD rate - create a customer without any outstanding balance - open the PoS, create an order of USD 100 and validate it with the Customer Account (Pay Later) payment method - open the Customers screen and look at the Total Due of that customer Issue: The Total Due shows about USD 55.56, i.e. the amount converted once too many, instead of the expected USD 100. Cause: get_total_due() sums two amounts that are not expressed in the same currency before converting them. partner.total_due comes from the accounting entries, it is the sum of account.move.line.amount_residual and is therefore in company currency, while total_settled is the sum of pos.payment.amount of the still open sessions, which is in the currency of the order, so the PoS one. The addition is done first and the result is then converted from the company currency to the PoS one, so the pay later payments end up converted a second time. opw-6403320 Forward-Port-Of: odoo/enterprise#126290 Forward-Port-Of: odoo/enterprise#125798
Features or functions removed from Odoo
An outdated automated test for structured references in accounting reconciliation was removed because the related behavior is no longer supported after a previous change. This keeps the test suite aligned with the current, simpler reconciliation setup and avoids misleading failures.
Original PR description
After merging pr #117256 the behavior for creating auto reconcile models for structured reference is no longer working so the test for checking that behavior should be removed. This was an FP request to use contains instead of regex in auto reconcile model creation because it was too complicated for users. no task id
7 changes
Enhancements to existing features
Before this commit, Peppol error messages (e.g. Schematron errors) were logged in the chatter as a single unformatted line and without any humanization. The errors were too technical and the user could not easily know what action to take. This PR splits the raw error payload into individual entries, maps known error codes to human-readable explanations, and renders them as an HTML list in the chatter. task-6144909 --- I confirm I have signed the CLA and read the PR guidelines at www.od
Original PR description
Before this commit, Peppol error messages (e.g. Schematron errors) were logged in the chatter as a single unformatted line and without any humanization. The errors were too technical and the user could not easily know what action to take. This PR splits the raw error payload into individual entries, maps known error codes to human-readable explanations, and renders them as an HTML list in the chatter. task-6144909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265253
This PR handles 2 cases : ===== PART 1 ===== Self-billing bill sequences should be unique per partner, as implemented in v19+. This PR backports that behavior to 17.0. ===== PART 2 ===== Previously, the `is_self_billing` option on `account.journal` was available only for purchase journals. This caused an issue when importing a self-billing invoice into a regular sales journal with quick edit mode (accounting firm) enabled. In such cases, the newly created invoices would use the self-
Original PR description
This PR handles 2 cases : ===== PART 1 ===== Self-billing bill sequences should be unique per partner, as implemented in v19+. This PR backports that behavior to 17.0. ===== PART 2 ===== Previously, the `is_self_billing` option on `account.journal` was available only for purchase journals. This caused an issue when importing a self-billing invoice into a regular sales journal with quick edit mode (accounting firm) enabled. In such cases, the newly created invoices would use the self-billing sequence pattern, leading to traceability issues. This PR allows the creation of self-billing sales journals to prevent this issue. task-6103142 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#259935
Resolved issues and error corrections
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots & Serial Numbers in Settings. - Create two products: Car and Engine. - Configure Engine to use Unique Serial Number tracking (Inventory →Traceability). - Set the on-hand quantity of Engine to 1 with serial number 0001. - Create a BoM for Car using Engine as a component. - Create and confirm a man
Original PR description
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots &…
Currently, users encounter a traceback when attempting to print the traceability report for a manufacturing order. ## Steps to produce: - Install Manufacturing without demo data. - Enable Lots & Serial Numbers in Settings. - Create two products: Car and Engine. - Configure Engine to use Unique Serial Number tracking (Inventory →Traceability). - Set the on-hand quantity of Engine to 1 with serial number 0001. - Create a BoM for Car using Engine as a component. - Create and confirm a manufacturing order for Car. - Click `Consumed` for the component and click Produce All. - Navigate to Lots & Serial Numbers → Engine → 0001 → Traceability. - Click the arrow next to the manufacturing order reference, then click Print. ## Observed Behavior: An `Arbitrary Uncaught Python Exception` traceback is raised, resulting in a 404 error. ## Root Cause: This issue occurs because, when the user clicks the arrow button in the traceability report, the template [1] invokes the `onClickUpDownStream` function. This function adds the URL `/stock/output_format/stock/active_id` to the context , as shown in [2]. Later, when the user clicks the Print button, `onClickPrint()` [3] constructs the print URL using the `controllerUrl` value by replacing the active model and active ID placeholders with values from the context. However, the URL stored in the context contains `/active_id` instead of `:active_id`. As a result, the placeholder replacement does not occur, leaving the URL unchanged. This causes the print action to use an invalid URL, ultimately resulting in a 404 error. As shown in [4], `controllerUrl` is assigned directly from the context. [1]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.xml#L52-L56 [2]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L105-L118 [3]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L120-L131 [4]: https://github.com/odoo/odoo/blob/a398ade607940a281552f8cba2c1cf80bb0e77f6/addons/stock/static/src/client_actions/stock_traceability_report_backend.js#L53-L55 ## Solution: Pass the correct URL in the context so that the active ID placeholder can be replaced correctly during the print action. This ensures that the generated print URL is valid, allowing the user to print the report without encountering any errors. opw-6372834 Forward-Port-Of: odoo/odoo#276449
opw-6410368
Original PR description
opw-6410368
If a vendor refund XML has a BaseQuantity node, it will multiply price_unit by -1 and every related amount by -1, Steps to reproduce: - import an Invoice XML having a single line with: - InvoicedQuantity -1 - LineExtensionAmount -100 - Price/PriceAmount 100 - Price/BaseQuantity 1 - VAT 21% Current behavior: Imported account move has: - line 1: product price: -100 and 21% VAT - line 2: rounding price: 200 and no tax - Untaxed amount 100€ - VAT -21€ - tota
Original PR description
If a vendor refund XML has a BaseQuantity node, it will multiply price_unit by -1 and every related amount by -1, Steps to reproduce: - import an Invoice XML having a single line with: - InvoicedQuantity -1 - LineExtensionAmount -100 - Price/PriceAmount 100 - Price/BaseQuantity 1 - VAT 21% Current behavior: Imported account move has: - line 1: product price: -100 and 21% VAT - line 2: rounding price: 200 and no tax - Untaxed amount 100€ - VAT -21€ - total amount 79€ Expected behavior: - line 1: product price of 100 and 21% VAT - Untaxed amount 100€ - VAT 21€ - total amount 121€ Task [link](https://www.odoo.com/odoo/project.task/6323022) opw-6323022
Step to reproduce: - install pos_restaurant with demo - open restaurant, for a table 1 order 3 items - in second tab, open kitchen display, there should be 1 order for table 1 - in pos, for same order split 1 item and transfer it to table 2 Observation: - splitting and transferring order does not update kitchen display Cause: - we found, doing above actions, never triggered the kitchen display for update Fix: - we know send a flag, if we have to notify the change to preparation d
Original PR description
Step to reproduce: - install pos_restaurant with demo - open restaurant, for a table 1 order 3 items - in second tab, open kitchen display, there should be 1 order for table 1 - in pos, for same order split 1 item and transfer it to table 2 Observation: - splitting and transferring order does not update kitchen display Cause: - we found, doing above actions, never triggered the kitchen display for update Fix: - we know send a flag, if we have to notify the change to preparation display opw-6390979 --- 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 receiving a mail with invalid utf-8, an error is thrown when trying to attach the mail to the record, so mail is never processed, if 50 or more mails with parsing errors are received, no new mails are received in Odoo. ### Current behavior before PR: Receive a email where the body can't be parsed by mail.message.as_string() -> error is raised when trying to attach eml file, so the mailbox isn't processed. ### Desired behavior
Original PR description
### Description of the issue/feature this PR addresses: When receiving a mail with invalid utf-8, an error is thrown when trying to attach the mail to the record, so mail is never processed, if 50 or more mails with parsing errors are received, no new mails are received in Odoo. ### Current behavior before PR: Receive a email where the body can't be parsed by mail.message.as_string() -> error is raised when trying to attach eml file, so the mailbox isn't processed. ### Desired behavior after PR is merged: Non parsable emails get attached as bytes instead of trying to parse them and failing to process the entire mail box. TT63730 @tecnativa --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr