Daily updates from Odoo
Navigate
Branch
Monday, June 22, 2026
376 changes
25 changes
Enhancements to existing features
This update strengthens the process of exporting Liasse Fiscale reports by implementing crucial data checks. Specifically, it verifies that key information related to writers, debtors, and referenced partners is complete and accurate before reports are generated and sent. This improves data reliability and reduces potential errors in tax reporting.
Original PR description
while exporting liasse fiscale, no chceks were done before the export and there were no account returns checks before sending it, this commit add account return checks to the liasse fiscale: -writer and debtor have the necessary informations on their record -partners mentionned in the reports have the necessary fields completed on their records -for some line, we have to choose between some values task-6127270
Resolved issues and error corrections
This update resolves an issue where leave schedules incorrectly blocked resource allocation, now only applying to resources with matching calendars. Additionally, tests have been reorganized and corrected to ensure accurate coverage of rental planning features, improving overall system stability and reliability.
Original PR description
## [FIX] sale_renting_planning: check global leaves working schedule Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated…
## [FIX] sale_renting_planning: check global leaves working schedule
Before this commit: any `resource.calendar.leaves` with no `resource_id` created would prevent all resources from being allocated during the leave date.
After this commit: any `resource.calendar.leaves` with `no resource_id` would be applied only to resources with the same `calendar_id` as the leave.
if the leave has no `calendar_id` then the leave applies to all `resource.calendars`
if a resource has no `calendar_id` then leaves with no `calendar_id` apply to it as well
## [IMP] {website_}sale_renting_planning: move tests from industry and fix existing ones
This commit moves the tests from [odoo/industry#1980](vscode-file://vscode-app/snap/code/237/usr/share/code/resources/app/out/vs/code/electron-browser/workbench/workbench.html) to their respective standard modules.
It also fixes the logic behind some tests as they weren't testing a `planning.role` with `sync_shift_rental` enabled.
task-6179505
Forward-Port-Of: odoo/enterprise#120865
Forward-Port-Of: odoo/enterprise#116430This update resolves an issue where focusing on the end date within a daterange widget incorrectly modified the start date. The fix ensures that the correct date field is updated when a user interacts with the input fields, improving data accuracy and reliability. This change was made to address a reported bug and enhance the user experience.
Original PR description
When a daterange widget is used (e.g., `deferred_start_date` coupled with `deferred_end_date`), focusing on the end date input was incorrectly modifying the start date field. This occurred because the `focusin` event was resolving the field name from the parent widget rather than the specific input focused. This commit updates `onFocusFieldWidget` and `getFullFieldName` to accept and evaluate the specific `event.target`. For `o_field_daterange` widgets, it now extracts the correct field name from the target's `data-field` attribute, ensuring the correct date field is updated. opw-6250048 Forward-Port-Of: odoo/enterprise#121033 Forward-Port-Of: odoo/enterprise#120684
This update enhances the Timesheet Assistant by streamlining suggestions, adding shortcuts, and correcting inaccuracies in hour calculations. Specifically, it removes distracting highlights, excludes leave time from totals, and improves the relevance of suggestions for timesheet creation.
Original PR description
## Expected Behavior After Commit - Remove the green highlight when selecting a suggestion. - Add shortcuts for timesheet creation buttons. - Allow calendar events to be considered side activities - Exclude leave time from total hours, as leave time is already counted in the timesheet. - Do not show to‑do tasks (tasks without a project) in suggestions. - Restore previous suggestions for to‑do tasks when they later become linked to a project. - Add a default name for suggestions that do not have one. - Add hotkeys to Timesheet Assistant task-[6191451](https://www.odoo.com/odoo/project/4105/tasks/6191451) Forward-Port-Of: odoo/enterprise#120057
This update corrects an error that prevented users from sending SMS messages to website visitors. The issue stemmed from a change in how visitor data was accessed. This fix ensures that the correct phone number is used when sending SMS messages, improving the functionality of the website CRM SMS feature.
Original PR description
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another…
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another `Form` block. - Configure the form action to `Create an Opportunity` and `save`. - Fill in the required fields, including phone number and `Submit` the form. - Go to `Website` > `Reporting` > `Visitors` and click the `SMS` button on the visitor record. `AttributeError: 'website.visitor' object has no attribute 'phone'` After [this commit], which removed the mobile field from res.partner along with all related views, then it was updated to access the phone number from the website visitor. When a user creates an opportunity through the website and then tries to send an sms from the corresponding visitor record, it raises an error [1] because it attempts to access the phone field on website.visitor. when an anonymous (non-logged-in) user creates an opportunity, clicking the sms button on the corresponding visitor record triggers error here [2]. This commit ensures that the correct mobile field is accessed from the website visitor. [this commit]: https://github.com/odoo/odoo/commit/6b820eb6fc6f782ba6a83d605d87b4a1dd2a87be [1]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L13 [2]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L20 sentry-7550340909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270118
This update clarifies the visual feedback when hovering over scrollbars in the HTML editor's syntax highlighting. Previously, a text cursor appeared, which was confusing. Now, the default cursor is displayed, providing a clearer indication that the scrollbar is for navigation only.
Original PR description
Current behavior before PR: - When a syntax highlighting block contained a scrollbar, hovering over the scrollbar displayed a text cursor. This was misleading because the text cursor suggests text interaction, while the scrollbar is only used for scrolling. Desired behavior after PR is merged: - The default cursor is now shown when hovering over the scrollbar, avoiding this confusion. task- 6295899 Forward-Port-Of: odoo/odoo#269728
This update resolves an issue impacting payroll calculations in both the UAE (AE) and Saudi Arabia (SA) localizations. The fix ensures accurate net cost calculations by standardizing how salary rules are aggregated, preventing negative values from incorrectly affecting payroll totals.
Original PR description
Steps: - Add a new salary category with the parent_id of company contribution (COMP) in AE - Create a dummy salary rule of that category - Compute a payslip and see the net cost unchanged Or - Create and compute a payslip in SA - Company contributions will be subtracted from each other Issue: - In AE localization, the issue with the rule was dropping salary rules that have a parent of company contribution category - In SA localization, the issue with the NETCOST was the aggregation of individual rules could include negative values which is not the intended flow. Solution: A standardized approach was adopted in both localizations in order to match the calculation of the NETCOST across. This approach will account for the categories with company contribution parent as well as the positive values for the individual salary rules. Forward-Port-Of: odoo/enterprise#115499
This update resolves a technical issue where Odoo would crash when attempting to calculate work hours for dates without associated calendar attendance. The fix ensures that the system returns 0 hours for these dates, preventing the error and maintaining accurate time tracking.
Original PR description
If we call the method _get_duration_based_work_hours_on_date on a date we are not supposed to work and that have no resource calendar attendance linked, it will crash. This commit fixes the issue by returning 0 hours in that specific case. 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
This update resolves an issue impacting how sickness pay is calculated for employees transitioning between long and partial periods of absence. The fix ensures accurate DPV (disabled person's verification) computations, particularly when moving from a long sickness to a partial incapacity. This improves the reliability of payroll processing.
Original PR description
Forward-Port-Of: odoo/enterprise#120868
This update fixes a limitation in how subscription products are priced, allowing users to accurately set one-time prices for hybrid subscriptions. Now, the system requires a plan to be selected for subscription products and ensures users can correctly configure pricing for products that allow both recurring and one-time sales. This enhances the flexibility and accuracy of subscription pricing.
Original PR description
Before this commit:
1. Users could save a pricelist rule for a pure subscription product without assigning a plan.
2. Hybrid subscription products (where 'Allow One-Time Sale' is True) were filtered out of the pricelist item form when no plan was selected, preventing users from setting a one-time price.
After this commit:
- The `plan_id` field on the product template form is now mandatory if the product is a subscription and does not allow one-time sales.
- The `product_tmpl_id` domain on the pricelist item form is updated to `['|', ('recurring_invoice', '=', bool(plan_id)), ('allow_one_time_sale', '=', True)]`, allowing users to select hybrid products for one-time pricing.
task: 6164232
Forward-Port-Of: odoo/enterprise#115271This update fixes a limitation in the CRM Lead data enrichment process. Previously, changes made to enriched lead records couldn't be saved. Now, updated records are returned, allowing users to accurately reflect the latest information and avoid data discrepancies. This ensures data consistency and improves the reliability of CRM reporting.
Original PR description
Return the enriched records to allow overrides. task-id: 5186595 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270244
This update fixes an issue where sending a chat request would automatically add users to the website live chat channel, leading to unwanted notifications. Now, sending a chat request only initiates the conversation without adding the user to the channel, improving user experience and reducing noise.
Original PR description
Sending a chat request to a visitor should not add the user to the website live chat channel. this prevents users from receiving unrelated future live chat conversations. task-6314123 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update fixes a bug that prevented customers from removing free shipping rewards once they were applied to their cart. The fix removes a restriction in the system that only handled discount rewards, now allowing free shipping and free product rewards to be removed as intended. This improves the customer experience and ensures accurate order totals.
Original PR description
Steps to produce: --- - Install `website_sale_loyalty`. - Go to `Website > ecommerece > Loyalty > DIscount & Loyalty`. - Create a new discount & loyalty program > set program type as `promotions`. -…
Steps to produce: --- - Install `website_sale_loyalty`. - Go to `Website > ecommerece > Loyalty > DIscount & Loyalty`. - Create a new discount & loyalty program > set program type as `promotions`. - Under Rewards, select `Free Shipping` as the reward type. - Create a product with a price of 1000 and publish it. - Add the product to the cart from the website. - Observe that free shipping is automatically applied on cart. - Attempt to remove the free shipping reward from the cart. Issue: --- - Free shipping (and similarly, free product rewards) cannot be removed from the cart once applied. Root cause: --- - At [1], the `website_sale_loyalty_delete` context is only passed when the reward type is `discount`. As a result, for free shipping and free product rewards, the context is not set. At [2], the order line is removed, but the reward is not added to `disabled_auto_rewards`. The `_auto_apply_rewards` method runs immediately afterward, detects the missing reward, and re-applies it automatically. Fix: --- - Since there are three reward types (discount, free shipping, and free product), the condition restricting the context to only discount rewards should be removed. [1]https://github.com/odoo/odoo/blob/5e90858fa91348f6aa33b4f8a246e77fbb8ea63f/addons/website_sale_loyalty/models/sale_order.py#L179 [2]https://github.com/odoo/odoo/blob/5e90858fa91348f6aa33b4f8a246e77fbb8ea63f/addons/website_sale_loyalty/models/sale_order_line.py#L15-L23 opw-6159288 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#261732
This update resolves an issue where milestone deadline dates disappeared from task views after navigating back or refreshing. The fix ensures that milestone deadlines are consistently displayed in the task Kanban view and task form views, improving project tracking accuracy.
Original PR description
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4.…
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4. Click the browser's back button (or simply refresh the page while on the task kanban view). Issue: Milestone deadline dates disappear from the task Kanban cards and headers after navigating back or reloading. Why this happens: When hitting the browser back button or refreshing, the web client's router state recovery workflow executes (`loadRouterState` -> `loadState` -> `doAction` -> `_executeActWindowAction`). During this flow, `_getActionParams` checks if it can reuse the cached `lastAction`. However, due to a safety condition introduced in commit ab26f95893 to prevent embedded action showing across different projects, the router falls back to generating a fresh action request via `state.action`. This forces `_loadAction` to fetch the action definition from the database. Because the original base action window `act_project_project_2_project_task_all` lacks the `display_milestone_deadline` key inside its default context dictionary, the reloaded view is rendered without the flags required by the frontend to display milestone deadlines. opw-6283514 Forward-Port-Of: odoo/odoo#269781
This update fixes a visual issue in the CRM's Kanban view where the progress bar wasn't accurately displaying the number of opportunities in each stage. The team removed a counter that was previously showing the 'Other' opportunity count, and this change restores that functionality, providing a clearer picture of pipeline activity. This ensures sales teams have a more accurate view of their progress.
Original PR description
# How to reproduce - Go to the CRM kanban view - Add an oppurtinity where the salesperson is yourself & add another one where it is not in Stage X - Enable the "My pipeline" filter - Hover the progress bar of Stage X # The problem The green part of the progress bar displays "X Planned" while the grey one displays "No activities scheduled" even if there are # Cause This commit introduced the change from "X Other" to "No activities scheduled" : https://github.com/odoo/odoo/commit/ec52375d3b99f42e712b8a44afee43d82ffdf239 But it removed the counter, which the PO wishes to add back opw-6229549 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265523
This update resolves a problem preventing certain manufacturing tests from running correctly when only the 'mrp' module is installed. The fix ensures the necessary product routes are available during test setup, allowing for consistent and reliable testing of the manufacturing workflow. This improves the stability and accuracy of our manufacturing test suite.
Original PR description
Launch any test of the `TestMultistepManufacturingWarehouse` by installing only mrp and teh setupCalss will fail since `route_ids` is not present in the view of the `product.template` as there is no product selectable routes with only mrp installed: https://github.com/odoo/odoo/blob/66127f790ec591456c2a562b7c224f81e6ec7b57/addons/stock/views/product_views.xml#L210-L220 However, products are created and edited using the Form class in the setupClass: https://github.com/odoo/odoo/blob/66127f790ec591456c2a562b7c224f81e6ec7b57/addons/mrp/tests/test_warehouse_multistep_manufacturing.py#L22-L40 runbot-238777 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270363
This update corrects a problem in how Odoo generates UBL BIS3 files for Debit Notes. Previously, the system incorrectly used 'LegalMonetaryTotal' instead of the required 'RequestedMonetaryTotal' node. This change ensures compliance with UBL BIS3 standards, improving the accuracy of our financial document exports.
Original PR description
Problem --------- Debit note should have the node `RequestedMonetaryTotal` instead of `LegalMonetaryTotal`. Solution --------- Add a conditional depending on the document type. opw-6295897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270238
This update fixes an issue in the Data Recycle app where record IDs were incorrectly summed and displayed alongside group names, causing truncation and unreadability. The change removes the unnecessary aggregation of record IDs, resulting in a cleaner and more informative display when grouping records.
Original PR description
## Issue In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="720" height="281" alt="115492" src="https://github.com/user-attachments/assets/567902af-b356-4a0a-8b1e-2ed101a2eba3" />
## Steps to reproduce
1. Install *Data Recycle* (`data_recycle`)
2. In Data Cleaning > Configuration > Recycle Records, create a new rule:
- Any name
- Model: *Contact*
- Filter: *Name contains G* (or anything else that matches some records)
4. Click the *Run Now* button in the upper left corner
5. In Data Cleaning > Recyle Records, group the records by any field (e.g., *Model*)
6. **The name of the group (Contact) is truncated, making it and the record count unreadable. This is due to the sum of Record ID being displayed in the same row, even though that information is irrelevant.**
## Cause
Similarly to related enterprise PR https://github.com/odoo/enterprise/pull/115492, the *Record ID* field of the `data_recycle.record` model uses the default `sum` aggregator.
https://github.com/odoo/odoo/blob/6de867f1c92bacedc0574b63e9e6a2a57fe805dd/addons/data_recycle/models/data_recycle_record.py#L17
related: https://github.com/odoo/enterprise/pull/115492
opw-6219824
Forward-Port-Of: odoo/odoo#265163This update resolves an issue in the Data Cleaning app where grouping records resulted in the record ID being incorrectly summed and displayed alongside group names, leading to truncated names and inaccurate counts. This change ensures group headers accurately reflect the number of records within each group.
Original PR description
## Issue In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="709" height="374" alt="6166623-before" src="https://github.com/user-attachments/assets/9d80b1ec-49c0-4b7f-8c6e-53846f9e433e" />
## Steps to reproduce
1. Install *Data Cleaning* (`data_cleaning`)
2. In Data Cleaning > Configuration > Field Cleaning, create a new rule (or edit an existing one):
- Any name
- Model: *Contact*
- Rule:
- Field to Clean: *Name (Contact)*
- Action: *Set Type Case* - Case: *All Uppercase*
4. Click the *Clean* button in the upper left corner
5. In Data Cleaning > Field Cleaning, group the records by any field (e.g., *Field*)
6. **The name of the group (_Name (Contact)_) is truncated, making it and the record count unreadable. This is due to the sum of _Record ID_ being displayed in the same row, even though that information is irrelevant.**
## Cause
The *Record ID* (`res_id`) field is an Integer field defined [here](https://github.com/odoo/enterprise/blob/3603afdd5c0d19c9276f3855156be4040ab5717d/data_cleaning/models/data_cleaning_record.py#L20). By default, Integer fields have the `sum` aggregator:
https://github.com/odoo/odoo/blob/681610c002a310f1c73fc2e5bec8d3dae27bc4a7/odoo/orm/fields_numeric.py#L17-L23
This causes the IDs to be summed up and appear in the group headers.
## After
<img width="740" height="370" alt="6166623-after" src="https://github.com/user-attachments/assets/a42d8f58-06dc-4308-8b6f-1ab09e8034f8" />
related: https://github.com/odoo/odoo/pull/265163
opw-6166623
Forward-Port-Of: odoo/enterprise#115492This update ensures that purchase order prices correctly preserve the precision of small product costs, like those below the standard currency decimal. Previously, prices were rounded, leading to inaccurate calculations. This change aligns purchase order pricing with sales order pricing, improving data accuracy and financial reporting.
Original PR description
Commit 07da917f6e331 introduced `min_display_digits` on product price fields, allowing small prices to be stored without forcing the global `Product Price` decimal precision to be increased. For…
Commit 07da917f6e331 introduced `min_display_digits` on product price fields, allowing small prices to be stored without forcing the global `Product Price` decimal precision to be increased. For example, a product can have a cost of `0.001235`. The value is kept on the product because `standard_price` uses `min_display_digits="Product Price"`. However, when this product is added to a purchase order line, the purchase price computation still explicitly rounds the computed unit price using the currency decimals and the `Product Price` decimal precision. This is inconsistent with sales: sale order lines preserve very small unit prices correctly. **Current behavior before PR:** A product with `standard_price = 0.001235` keeps that value on the product form. When adding the product to a purchase order line, the computed `price_unit` is rounded by `purchase.order.line`, so the small price is lost. The same issue can happen with vendor prices: a supplierinfo price with more precision than the currency decimals is rounded before being assigned to the purchase order line. **Desired behavior after PR is merged:** Purchase order lines preserve the computed unit price precision, just like sale order lines already do. A product cost or vendor price such as `0.001235` remains `0.001235` on the purchase order line instead of being rounded to currency/Product Price precision. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269413 Forward-Port-Of: odoo/odoo#267941
This update fixes an issue where stock valuation calculations were incorrect when a product had no recorded value. The fix ensures all products are considered during valuation replays, resulting in accurate inventory accounting. This improves the reliability of financial reporting.
Original PR description
Usecase to reproduce: - Create two average product A and B - Delele all the product.value for B - Receipt both units at 10$ - Set the price unit of A to 20$ - Receipt both units at 20$ Check the value at date to trigger a replay of valuation Expected behavior: - Product A -> 20 units at 20$ -> 400$ - Product B -> 20 units at 15$ -> 300$ Current behavior: - Correct for A but B is 200$ It happens because when we replay the history, we check for the minimal product.value and we replay valuation from this date (with moves). However in our case, the product B has no product value and thus we replay from A product.value. However it arrives after the first receipt of B and thus we only consider the second receipt for B. This is fixed by ensuring we have a product.value for all products in order to add a date domain on the moves. Forward-Port-Of: odoo/odoo#255909 Forward-Port-Of: odoo/odoo#255787
This update fixes an issue where product costs weren't correctly converted to the POS currency. Previously, product costs were stored in separate currencies, leading to potential inaccuracies in pricing. This change ensures all product costs are accurately converted, improving the reliability of sales data in the Point of Sale system.
Original PR description
When loading products in the POS, both the sale price and the cost were converted to the POS currency using `currency_id`. However a product stores its sale price and its cost in two potentially different currencies: `currency_id` (company currency, falling back to the main company) and `cost_currency_id` (company currency, falling back to the current company). opw-6297452 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269829
This update resolves a technical error that prevented the notification popover from displaying correctly when adding a follower to an event. The issue stemmed from a missing 'res_partner_id' field, which caused a comparison error. This fix ensures that the notification popover functions correctly for all users, regardless of whether a partner ID is present.
Original PR description
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When…
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When clicking on the enveloppe, we display the `message_notification_popover` that calls `isFollowerNotification` to filter follower notifications from other ones. This function compares the ids of the followers of the notification to it's res_partner_id : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/static/src/core/common/notification_model.js#L101-L105 But in our case res_partner_id is undefined because it is not a required field and it will not be set in the case of mass_mailing : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/models/mail_notification.py#L23-L27 opw-6178443 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265263
This update fixes an issue where preparation prints weren't showing all items after transferring a restaurant order to a shared table. The fix ensures that all products from both orders are accurately reflected on the preparation reprint, improving kitchen efficiency and order accuracy. It addresses a technical problem related to how order history is managed during merging.
Original PR description
When moving an order (Order A) to a table that already has an order (Order B), the merged order only reprints Order B's products. The products from Order A are missing from the preparation reprint.…
When moving an order (Order A) to a table that already has an order (Order B), the merged order only reprints Order B's products. The products from Order A are missing from the preparation reprint. Steps to reproduce: ------------------- * Open a POS session on a Restaurant POS * Create an order (Order A) for Table 1 * Create a second order (Order B) for Table 2 * Transfer/Merge Order A to Table 2 * Reprint the preparation order > Observation: Only the products that were already on Table 2 (Order B) appear on the reprint. Products from Order A are missing. Why the fix: ------------ mergeOrders correctly transfers kitchen history (last_order_preparation_change.lines) via handlePreparationHistory, but does not update uiState.lastPrints on the destination order. The reprint button uses lastPrints.at(-1) when there are no pending changes, so it only shows the destination order's last print batch — ignoring the merged lines entirely. Implementation: After the merge loop, build a consolidated lastPrints entry from the destination order's last_order_preparation_change.lines (which now contains lines from both orders) and push it onto destOrder.uiState.lastPrints so that reprint reflects the full merged state. opw-6060684 Forward-Port-Of: odoo/odoo#270311 Forward-Port-Of: odoo/odoo#256309
This update fixes inaccurate Cost of Goods Sold (COGS) calculations for kit products in Odoo. The change ensures kits are correctly valued, addressing issues with multiple steps, multiple kits in a BOM, and FIFO inventory accounting. The fix simplifies the calculation and improves test coverage.
Original PR description
There's a few problems with kits and cogs This PR fixes them and unskips most tests of the test class. **Problems:** - Problem 1 multiple steps delivery - steps to reproduce: - activate 3 steps…
There's a few problems with kits and cogs
This PR fixes them and unskips most tests
of the test class.
**Problems:**
- Problem 1 multiple steps delivery
- steps to reproduce:
- activate 3 steps delivery
- create 2 storable products 'comp A' and 'comp B'
with category standard perpetual
- for both : set a cost of 10 and on on hand quantity
- create a storable kit product with category standard perpetual
- create a kit bom for the kit product with 1 comp A and 1 comp B
- confirm a SO for 1 quantity of the kit prod
- validate only first delivery
- confirm invoice
- Current behaviour:
No cogs line
- expected behaviour :
There should be cogs for 20$
- Problem 2 multiple kits in Bom :
- steps to reproduce:
- (multiple steps delivery not needed)
- use same products as for problem 1 but, in the Bom, set
the number of kit products produced to 2
- confirm a SO for 2 quantity of the kit prod
- validate all pickings
- confirm invoice
- Current behaviour:
Cogs have a value of 10$
- expected behaviour :
There should be cogs for 20$
- Problem 3: fifo comp
- steps to reproduce:
- with 1 step delivery
- create a storable product 'comp A' with fifo perpetual
category
- Confirm a PO and validate receipt for 1 comp A at 10
- Confirm a PO and validate receipt for 1 comp A at 20
- create a storable product 'kit' with fifo perpetual categ
- create a kit bom for the kit product with 1 comp A
- confirm SO for 2 kit
- deliver 1 quantity and create backorder
- confirm invoice for 1
- COGS line are created for 10$ (as expected)
- deliver the backorder
- confirm invoice for 1
- Current Behaviour:
Cogs are created for 15$
- Expected Behaviour:
Cogs should be created for 20$
**Cause of the issues:**
To compute the price_unit used for the cogs we call
_get_cogs_value()
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/stock_account/models/account_move.py#L122
What we want is the price unit for 1 unit of the kit product
So we want :
sum(unit price of each comp * quantity of comp in bom)/ quantity of kit in bom
What is done for now :
Inside the sale_mrp override, for each component of
the bom we call _get_price_unit() on its move and
add the value to 'average_price_unit' and then divide
by the quantity of the kit product in the bom
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/sale_mrp/models/account_move.py#L38-L42
Inside the sale_mrp override of _get_price_unit()
we return _get_kit_price_unit() called on the move,
https://github.com/odoo/odoo/blob/f8741728294a5147c7d2427d9997738096386262/addons/sale_mrp/models/stock_move.py#L15
Inside _get_kit_price_unit(), the variable 'component_qty_per_kit',
contains the quantity of each component as recorded in the bom
times the valued quantity (sale order line quantity).
For each comp :
- we store the return value of _get_price_unit
called on its moves in 'price_unit'.
- we add to 'total_price_unit':
price_unit * component_qty_per_kit/ the kit qty in the bom
we then return total_price_unit / valued quantity
So we actually return:
sum(unit price of each comp * quantity of comp in bom*
valued quantity)/ (quantity of kit in bom * valued quantity)
which is equal to:
sum(unit price of each comp *quantity of comp in bom)
/ quantity of kit in bom
https://github.com/odoo/odoo/blob/38c737c2a4cc29b48235a100cfa9d6152af73826/addons/mrp_account/models/stock_move.py#L40-L44
Problem 1 is caused by the fact that _get_price_unit()
will return 0 if there's only internal moves because
they have a value of 0.
(The problem does not happen with a single component
cause then the fallback on the super method is correct, but
with multiple comp the super method also returns 0
because _get_cogs_price_unit returns 0 when more than
one product).
Problem 2 is caused by the fact that we divide by the
quantity of the kit in the bom (kit_bom.product_qty) here
(inside _get_kit_price_unit) and again inside _get_cogs_value
as mentionned before.
Problem 3 happens because there is no mechanism
to account for already posted cogs inside the sale_mrp
override of _get_cogs_value(), as qty_invoiced
is computed but never used
https://github.com/odoo/odoo/blob/38c737c2a4cc29b48235a100cfa9d6152af73826/addons/sale_mrp/models/account_move.py#L31
**Fix**
As regards to the super methods (so non kit scenario),
_get_cogs_value() is used to :
- use original invoice if needed
- use standard price of the product if no moves
- deduct already posted cogs
- calls get _get_cogs_price_unit() to compute price_unit
based on the moves
All of this is also wanted for kits and don't need adaptation,
therefore the override should be on the _get_cogs_price_unit
where we do need a different behaviour when the product is a kit
Doing this we benefit from the 'already posted mechanism'
from _get_cogs_value which solves problem 3
Additionally, instead of calling get_price_unit we can directly
call the super method _get_cogs_price_unit as we have
already computed all the components quantities needed
for our computation and therefore don't need
_get_kit_price_unit to recompute all of this.
Also, _get_cogs_price_unit will fall back on the product
standard price if the move has no value which solves
problem 1.
That will also prevent dividing twice by the quantity
of kit product in the bom (bom.product_qty)
which solves problem2.
**Tests:**
Out of the 9 existing tests of the class (that were skipped
before this PR) and after adapation to v19 valuation :
- 2 succeeded before and after the fix : this PR unskips them
- 5 failed before the fix and now suceed with the fix : this PR
unskips them
- 2 failed before the fix and after the fix, they were let
skipped
In addition, 2 tests were added to cover problem 1 and 3
(problem 2 is covered in test test_sale_mrp_kit_bom_cogs)
Forward-Port-Of: odoo/odoo#270675
Forward-Port-Of: odoo/odoo#27007521 changes
Resolved issues and error corrections
This fix resolves an issue preventing the 'Send to SII' option from appearing on Chilean vendor bills. The update adjusts internal code to correctly display this button when a DTE is generated, ensuring invoices can be properly transmitted to the SII (Servicio de Impuestos Internos) as required by Chilean regulations. This improves compliance and streamlines the invoicing process.
Original PR description
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF…
**Steps to reproduce:** * Install the **l10n_cl_edi** module. * Go to **Accounting → Configuration → CAFs**, create a new CAF, and upload a valid CAF [XML](https://www.odoo.com/mail/message/1097235975) file. * Create a new **Purchase Journal** with **Use Documents** enabled. * Create a vendor bill using this journal. * Set the **Document Type** to **46 - Liquidación-Factura Electrónica**. * Confirm the vendor bill. **Observed behavior:** * The Send button is not visible on the confirmed vendor bill despite the DTE being generated and `l10n_cl_dte_status` being set to `not_sent`. **Cause:** * `_compute_display_send_button` in `account` only returns `True` for sale documents (`is_sale_document()`), so the "Send" button — which opens the Send & Print dialog containing the "Send to SII" option — was never shown on vendor bills. * `_get_move_constraints` in `account.move.send` unconditionally adds a `not_sale_document` constraint for non-sale documents, blocking the Send & Print dialog from processing vendor bills even if the button were visible. * The cron's `cron_run_sii_workflow` only processes moves with `l10n_cl_dte_status = 'ask_for_status'`, skipping moves still in `not_sent` state. **Fix:** * Override `_compute_display_send_button` in `l10n_cl_edi` to also show the "Send" button on posted moves with `l10n_cl_dte_status == 'not_sent'`, matching the pattern used by `l10n_br_edi`. * Override `_get_move_constraints` in `l10n_cl_edi` to remove the `not_sale_document` constraint for Chilean purchase documents with `not_sent` status, matching the pattern used by `l10n_br_edi`. **REF** During this [refactor](https://github.com/odoo/enterprise/pull/103427/changes/f5617ecf7584cf019897408df94b002622f48d9d), these two methods were inadvertently missed and were not overridden opw-6300571
This update resolves a test failure related to GCC POS localization reporting. The fix ensures that order receipts display the correct information and addresses assertions related to rounding and discounts. This improves the reliability of the GCC POS test suite.
Original PR description
- Fixed `TestGenericGCC.test_generic_localization` which was failing because some information was not rendered on the order receipt. - Added rounding configuration to the POS config so that the assertion for `Rounding` does not fail. - Added steps for `Discount` and `Change` in `generic_localization_tour` so that the assertions for `Discount` and `Change` do not fail. Error-237988 Task-5897376 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update resolves a crash that occurred when users manually corrected bank statement lines within the Odoo Enterprise system. The issue stemmed from a missing context key during record creation, leading to incorrect journal assignments. This fix ensures bank statement lines are created with the correct journal, preventing data inconsistencies and system instability.
Original PR description
When the manual correction tool was used to fill in the lines, we weren't passing the active context when creating the new records. In the case of bank statements, it could be an issue as the `default_journal_id` key is expected to be present to set the correct journal on the newly created bank statement line. Without this key in the context, it would default to the first journal with a valid type (see function `_search_default_journal`). If the journal found this way didn't match the current journal, a crash would occur when modifying the newly created lines. opw-[6294117](https://www.odoo.com/odoo/unassigned-tasks/6294117) Forward-Port-Of: odoo/enterprise#121032 Forward-Port-Of: odoo/enterprise#120745
This update corrects a previous issue where fully settled customers with past pay-later payments were incorrectly prevented from seeing their Customer Statements. The fix now checks for any past pay-later payment lines, ensuring the statement button appears regardless of whether the customer's total balance is zero. This improves the user experience for all customers.
Original PR description
The override of _compute_has_moves was checking `total_due != 0` to set `has_moves` on for PoS pay_later customers. Once the customer is fully settled however, `total_due` is 0 and the check does not pass anymore, so `has_moves` goes back to `False` and the Customer Statement button hides for them, even though they had past pay_later payment lines. The fix is to check directly for any past pay_later `pos.payment` instead, which covers the cases where partner had used pay_later payment methods before, regardless if they have settled their total due or not. opw-6173760 Forward-Port-Of: odoo/enterprise#120911 Forward-Port-Of: odoo/enterprise#116536
This update resolves an issue where sending NFC-e invoices through IAP would halt the POS synchronization process when IAP credits were exhausted. The change prevents the system from blocking POS updates, ensuring smoother operations when IAP credit limits are reached. This improves reliability and prevents disruptions to sales workflows.
Original PR description
When sending an NFC-e, tax calculation is done by calling Avatax through IAP. If the IAP account has no credits left, iap_jsonrpc() raises an InsufficientCreditError. opw-6290857 Forward-Port-Of: odoo/enterprise#120700
This update resolves an error that prevented users from sending SMS messages to website visitors. The change updated how the system accesses visitor phone numbers, ensuring compatibility after a recent data restructuring. This ensures the SMS functionality works correctly for all visitors.
Original PR description
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another…
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another `Form` block. - Configure the form action to `Create an Opportunity` and `save`. - Fill in the required fields, including phone number and `Submit` the form. - Go to `Website` > `Reporting` > `Visitors` and click the `SMS` button on the visitor record. `AttributeError: 'website.visitor' object has no attribute 'phone'` After [this commit], which removed the mobile field from res.partner along with all related views, then it was updated to access the phone number from the website visitor. When a user creates an opportunity through the website and then tries to send an sms from the corresponding visitor record, it raises an error [1] because it attempts to access the phone field on website.visitor. when an anonymous (non-logged-in) user creates an opportunity, clicking the sms button on the corresponding visitor record triggers error here [2]. This commit ensures that the correct mobile field is accessed from the website visitor. [this commit]: https://github.com/odoo/odoo/commit/6b820eb6fc6f782ba6a83d605d87b4a1dd2a87be [1]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L13 [2]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L20 sentry-7550340909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270118
This update resolves an issue where text entered into a SelectMenu field was intermittently being cleared, causing data entry problems. The fix ensures the input field accurately reflects user input during asynchronous data updates, improving data accuracy and user experience. It also corrects a related issue with the SelectMenu clearing when empty.
Original PR description
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all…
Step to reproduce: 1. Install `website_link` 2. Open Website > Site > Link Tracker 3. Type in text into any pre-defined field (Campaign, Medium, Source) 4. Observe that the input is not showing all the typed characters Issue: - It's randomly removing characters, for example, type "1234567890" and observe Cause: - SelectMenu updates its internal searchValue only inside the debounced onInput handler `debouncedOnInput`. When an autocomplete callback reloads choices before that debounce fires, the component rerenders with a stale searchValue and writes that outdated value back into the controlled input, overwriting newer characters already typed by the user. Solution: - Update searchValue immediately on every raw input event and keep only the search callback debounced. - Also reset searchValue to null when a required single-select is blurred while empty, so the input falls back to the selected choice label instead of staying visually cleared. opw-6000540 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#267974 Forward-Port-Of: odoo/odoo#255819
A bug preventing users from adding cover images to Knowledge articles has been resolved. The issue stemmed from a missing callback function during the upload process, causing the upload to fail. This update ensures cover images can now be successfully added, improving the article creation experience.
Original PR description
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback:…
Steps to reproduce: 1. Install Knowledge. 2. Create an article. 3. Open the more actions menu. 4. Click "Add Cover". 5. Upload a cover image. Issue: - The upload crashes with the following traceback: `Uncaught Promise > this.props.setAbortUploadsCallback is not a function` Cause: - `KnowledgeCoverSelector` extends the html_editor `ImageSelector`, whose upload flow registers an abort callback through setAbortUploadsCallback. The generic MediaDialog provides this callback, but KnowledgeCoverDialog renders KnowledgeCoverSelector directly and did not pass it. As a result, the inherited upload flow called a missing prop. Solution: - Pass setAbortUploadsCallback from KnowledgeCoverDialog to KnowledgeCoverSelector and abort pending uploads when the cover dialog is discarded. Alternative approach: - Make ImageSelector tolerate callers that do not provide setAbortUploadsCallback by calling it with optional chaining. opw-6176716 Forward-Port-Of: odoo/enterprise#120467 Forward-Port-Of: odoo/enterprise#116906
This update resolves an issue where users with limited accounting permissions couldn't properly reconcile bank statements, leading to invoices being incorrectly marked as fully paid. The fix ensures accurate reconciliation by safely bypassing a permission check during the automated process, maintaining data auditability and preventing incorrect Account Receivable line additions.
Original PR description
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only…
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only "Invoicing & Banks" rights tries to reconcile a Bank Statement with the same partner, amount, and the invoice name as the memo, the automatic reconciliation fails to properly match the payment Instead, the invoice is incorrectly considered as Fully Paid with an unwanted extra Account Receivable line added ### Cause When a new Bank Statement is created, `_try_auto_reconcile_statement_lines()` is called and matches the outstanding credit, which invokes `set_line_bank_statement_line()` In 19.0, this function creates a balancing line and triggers `move._compute_checked()` to update dependencies Especially `_compute_is_reconciled` But checked as been replaced by `review_state` This FW port will use an update on the `review_state` instead of the `checked` A user with "Invoicing & Banks" rights lacks the `account.group_account_user` group, meaning the move is not marked as `reviewed`, preventing dependencies from computing correctly Consequently, the statement line's `amount_residual` is not cleared and the line is not removed from `remaining_st_line_ids` Later in the process, `_try_auto_reconcile_statement_lines()` is called again with `with_user(SUPERUSER_ID)` Because the payment matching was never finalized in the previous step, the engine fallback matches against the full invoice, adding an incorrect Account Receivable line to close it ### Steps to reproduce - Install `accountant` - Go to Accounting / Configuration / Accounting / Journals - Open the Bank, under Incoming Payments tab, set the Manual Payment method's Outstanding Receipts account to 101403 Outstanding Receipts - Update the Demo user's accounting rights to Invoicing & Banks - Log in with the Demo user - Create and confirm an invoice for Acme Corporation (Amount: $1100) - Register a payment on the invoice (Amount: $500, Keep open) - Copy the invoice name - Open the Bank Reconciliation widget from the Accounting Dashboard - Create and add a new Bank Statement Line (Label: Invoice name, Partner: Acme Corporation, Amount: $500) Before the fix, an unexpected Account Receivable line is created and the invoice is marked as Fully Paid ### Notes Instead of processing the entire block under SUPERUSER_ID, which would hide the creator identity in logs and chatter, the context key `skip_account_review_check=True` is injected during the automated statement line reconciliation This safely bypasses the group check inside `_is_user_able_to_review` for this specific automated flow A fallback using `.with_user(SUPERUSER_ID)` is already implemented twice within the same `_try_auto_reconcile_statement_lines` method for this specific use case, but avoiding it here preserves data auditability opw-6077137 Forward-Port-Of: odoo/odoo#270080
This update resolves an issue where users with restricted accounting rights incorrectly marked invoices as fully paid, leading to incorrect Account Receivable entries. The fix ensures automatic bank reconciliation works correctly for these users by safely bypassing a group check during the reconciliation process, maintaining data auditability.
Original PR description
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only…
### Issue When you have an invoice partially paid via a method using an Outstanding Account, the payment can be kept open, leaving the invoice considered as partially paid If a user with only "Invoicing & Banks" rights tries to reconcile a Bank Statement with the same partner, amount, and the invoice name as the memo, the automatic reconciliation fails to properly match the payment Instead, the invoice is incorrectly considered as Fully Paid with an unwanted extra Account Receivable line added ### Cause When a new Bank Statement is created, `_try_auto_reconcile_statement_lines()` is called and matches the outstanding credit, which invokes `set_line_bank_statement_line()` This function creates a balancing line and triggers `move._compute_checked()` to update dependencies However, `move.checked` requires `_is_user_able_to_review()` to be True A user with "Invoicing & Banks" rights lacks the `account.group_account_user` group, meaning the move is not marked as checked, preventing dependencies from computing correctly Consequently, the statement line's `amount_residual` is not cleared and the line is not removed from `remaining_st_line_ids` Later in the process, `_try_auto_reconcile_statement_lines()` is called again with `with_user(SUPERUSER_ID)` Because the payment matching was never finalized in the previous step, the engine fallback matches against the full invoice, adding an incorrect Account Receivable line to close it ### Steps to reproduce - Install `accountant` - Go to Accounting / Configuration / Accounting / Journals - Open the Bank, under Incoming Payments tab, set the Manual Payment method's Outstanding Receipts account to 101403 Outstanding Receipts - Update the Demo user's accounting rights to Invoicing & Banks - Log in with the Demo user - Create and confirm an invoice for Acme Corporation (Amount: $1100) - Register a payment on the invoice (Amount: $500, Keep open) - Copy the invoice name - Open the Bank Reconciliation widget from the Accounting Dashboard - Create and add a new Bank Statement Line (Label: Invoice name, Partner: Acme Corporation, Amount: $500) Before the fix, an unexpected Account Receivable line is created and the invoice is marked as Fully Paid ### Notes Instead of processing the entire block under SUPERUSER_ID, which would hide the creator identity in logs and chatter, the context key `skip_account_review_check=True` is injected during the automated statement line reconciliation This safely bypasses the group check inside `_is_user_able_to_review` for this specific automated flow A fallback using `.with_user(SUPERUSER_ID)` is already implemented twice within the same `_try_auto_reconcile_statement_lines` method for this specific use case, but avoiding it here preserves data auditability opw-6077137 Forward-Port-Of: odoo/enterprise#120217 Forward-Port-Of: odoo/enterprise#118023
This update resolves an issue where milestone deadline dates would disappear from task views after navigating back or refreshing. The fix ensures that milestone deadlines are consistently displayed in task Kanban cards and headers, regardless of user navigation, improving project tracking accuracy.
Original PR description
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4.…
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4. Click the browser's back button (or simply refresh the page while on the task kanban view). Issue: Milestone deadline dates disappear from the task Kanban cards and headers after navigating back or reloading. Why this happens: When hitting the browser back button or refreshing, the web client's router state recovery workflow executes (`loadRouterState` -> `loadState` -> `doAction` -> `_executeActWindowAction`). During this flow, `_getActionParams` checks if it can reuse the cached `lastAction`. However, due to a safety condition introduced in commit ab26f95893 to prevent embedded action showing across different projects, the router falls back to generating a fresh action request via `state.action`. This forces `_loadAction` to fetch the action definition from the database. Because the original base action window `act_project_project_2_project_task_all` lacks the `display_milestone_deadline` key inside its default context dictionary, the reloaded view is rendered without the flags required by the frontend to display milestone deadlines. opw-6283514 Forward-Port-Of: odoo/odoo#269781
This update prevents logged-in users from attempting to sign up or log in through the website's signup page. Previously, users could submit the form, resulting in an error. Now, a warning message appears, and the button is disabled, ensuring only new users can register.
Original PR description
Steps to reproduce: 1.Log in to the backend as an Admin (or any authenticated user). 2.Navigate to Website -> Configuration -> System Pages and open the Signup page. 3.Fill in the signup form and submit it. 4.After successfully signing up, click the Logout button. 5.Observe that a "405 Method Not Allowed" error is displayed. Before this commit: When an already logged-in user accessed the signup page through the System Pages menu and submitted the signup form, clicking the Logout button afterward resulted in a 405 Method Not Allowed error. After this commit: When an already logged-in user accesses the signup or login page, a warning message is displayed and the Sign Up or Log In button is disabled, preventing the form from being submitted. task-6023075 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#263791
This update clarifies timesheet reporting by changing the automated rule (AW Rule) to display the name of the GitHub pull request instead of its ID. This provides users with more context, making it easier to link pull requests to the relevant projects and tasks within the Timesheets Assistant.
Original PR description
Before this commit, the AW Rule used in Timesheets Assistant will display the id of the Github Pull request and the repository but that information is not always clear for the user to know which project/task is related to that PR. This commit changes the AW rule for Github to display the name of the pull request instead to have more context to easily match the project/task to the event created by that rule. task-6306166
This update improves the speed of queries related to document access permissions, specifically for the 'my/counters' route which is frequently used. By switching to a subquery, the system now utilizes an index more effectively, resulting in a significant reduction in query response times for portal and internal users.
Original PR description
The '/my/counters' route is hit a lot of times on big databases like odoo.com One thing it does is a `self.env['documents.document].search_count([])` With this commit, we use a subquery for the…
The '/my/counters' route is hit a lot of times on big databases like odoo.com
One thing it does is a `self.env['documents.document].search_count([])`
With this commit, we use a subquery for the folder access instead of the current LEFT JOIN.
This ok since the number of folders is typically small compared to regular documents and the query is fast since it can use the index on 'type'
Before as portal user
------
2x Seq Scan
```
Aggregate (cost=1900290.73..1900290.74 rows=1 width=8) (actual time=282.271..282.276 rows=1 loops=1)
Buffers: shared hit=66629
-> Hash Left Join (cost=41649.94..1900044.55 rows=98472 width=0) (actual time=184.202..282.267 rows=3 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 6) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 6))) OR (((documents_document.access_via_link)::text = ANY ('{edit,view}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 6) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 6)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 28085
Buffers: shared hit=66629
-> Seq Scan on documents_document (cost=0.00..1857903.54 rows=187073 width=26) (actual time=0.022..109.288 rows=28088 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 342576
Buffers: shared hit=33313
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=2)
Buffers: shared hit=6
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=2)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=6
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
-> Hash (cost=37016.64..37016.64 rows=370664 width=16) (actual time=164.521..164.521 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 17824kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=16) (actual time=0.005..100.491 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.003..0.003 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.002..0.003 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:16:38'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=69
Planning Time: 1.708 ms
Execution Time: 282.344 ms
```
After as portal user
-----
Only 1x Seq Scan
```
Aggregate (cost=2004948.33..2004948.34 rows=1 width=8) (actual time=116.161..116.165 rows=1 loops=1)
Buffers: shared hit=37942
-> Seq Scan on documents_document (cost=145660.16..2004490.36 rows=183187 width=0) (actual time=24.635..116.155 rows=3 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))) OR (((access_via_link)::text = ANY ('{edit,view}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 370661
Buffers: shared hit=37942
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.008..0.009 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.008..0.008 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145625.73 rows=13772 width=4) (actual time=11.688..11.689 rows=0 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 6) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 6))))
Rows Removed by Filter: 28198
Buffers: shared hit=4629
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.002..0.002 rows=0 loops=1)
Buffers: shared hit=3
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.001..0.002 rows=0 loops=1)
Index Cond: (partner_id = 7)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 10:15:10'::timestamp without time zone))
Buffers: shared hit=3
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (never executed)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Planning:
Buffers: shared hit=56
Planning Time: 1.544 ms
Execution Time: 116.216 ms
```
Before as internal user
--------
```
Aggregate (cost=1902165.43..1902165.44 rows=1 width=8) (actual time=332.919..332.925 rows=1 loops=1)
Buffers: shared hit=69223 read=370
-> Hash Left Join (cost=41649.94..1901908.04 rows=102955 width=0) (actual time=176.179..332.325 rows=10040 loops=1)
Hash Cond: (documents_document.folder_id = documents_document__folder_id.id)
Filter: ((hashed SubPlan 2) OR ((documents_document.owner_id = 1054906) AND ((documents_document.shortcut_document_id IS NULL) OR (documents_document.shortcut_document_owner_id = 1054906))) OR (((documents_document.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document.company_id = 1) OR (documents_document.company_id IS NULL))) OR (((documents_document.access_via_link)::text = ANY ('{view,edit}'::text[])) AND (documents_document.folder_id IS NOT NULL) AND ((hashed SubPlan 4) OR ((documents_document__folder_id.owner_id = 1054906) AND ((documents_document__folder_id.shortcut_document_id IS NULL) OR (documents_document__folder_id.shortcut_document_owner_id = 1054906))) OR (((documents_document__folder_id.access_internal)::text = ANY ('{view,edit}'::text[])) AND ((documents_document__folder_id.company_id = 1) OR (documents_document__folder_id.company_id IS NULL)))) AND (documents_document.is_access_via_link_hidden IS NOT TRUE)))
Rows Removed by Filter: 27228
Buffers: shared hit=69223 read=370
-> Seq Scan on documents_document (cost=0.00..1859756.86 rows=190950 width=35) (actual time=15.029..155.718 rows=37268 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (folder_id IS NOT NULL) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 333396
Buffers: shared hit=33931 read=370
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.155..7.920 rows=148 loops=2)
Buffers: shared hit=1612 read=370
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.110..3.448 rows=200 loops=2)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=192 read=190
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.022..0.022 rows=1 loops=400)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=1420 read=180
-> Hash (cost=37016.64..37016.64 rows=370664 width=25) (actual time=157.822..157.823 rows=370664 loops=1)
Buckets: 524288 Batches: 1 Memory Usage: 21336kB
Buffers: shared hit=33310
-> Seq Scan on documents_document documents_document__folder_id (cost=0.00..37016.64 rows=370664 width=25) (actual time=0.005..96.730 rows=370664 loops=1)
Buffers: shared hit=33310
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..0.372 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.005..0.078 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:17:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=69 read=8
Planning Time: 2.116 ms
Execution Time: 333.013 ms
```
After as internal user
--------
```
Aggregate (cost=2006950.17..2006950.18 rows=1 width=8) (actual time=157.117..157.121 rows=1 loops=1)
Buffers: shared hit=39918
-> Seq Scan on documents_document (cost=145798.74..2006482.26 rows=187165 width=0) (actual time=16.595..156.590 rows=10040 loops=1)
Filter: ((active IS TRUE) AND ((hashed SubPlan 2) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))) OR (((access_via_link)::text = ANY ('{view,edit}'::text[])) AND (hashed SubPlan 5) AND (is_access_via_link_hidden IS NOT TRUE))))
Rows Removed by Filter: 360624
Buffers: shared hit=39918
SubPlan 2
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.019..1.016 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access (cost=0.43..105.55 rows=103 width=9) (actual time=0.012..0.262 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id (cost=0.42..2.44 rows=1 width=9) (actual time=0.004..0.004 rows=1 loops=200)
Index Cond: (id = documents_access.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
SubPlan 5
-> Index Scan using documents_document__type_index on documents_document documents_document_1 (cost=0.42..145763.43 rows=14124 width=4) (actual time=0.429..14.916 rows=4625 loops=1)
Index Cond: ((type)::text = 'folder'::text)
Filter: ((hashed SubPlan 4) OR ((owner_id = 1054906) AND ((shortcut_document_id IS NULL) OR (shortcut_document_owner_id = 1054906))) OR (((access_internal)::text = ANY ('{view,edit}'::text[])) AND ((company_id = 1) OR (company_id IS NULL))))
Rows Removed by Filter: 23573
Buffers: shared hit=5617
SubPlan 4
-> Nested Loop (cost=0.85..357.41 rows=99 width=4) (actual time=0.007..0.390 rows=148 loops=1)
Buffers: shared hit=991
-> Index Scan using documents_access__partner_id_index on documents_access documents_access_1 (cost=0.43..105.55 rows=103 width=9) (actual time=0.003..0.074 rows=200 loops=1)
Index Cond: (partner_id = 1800102)
Filter: ((expiration_date IS NULL) OR (expiration_date >= '2026-06-18 12:16:29'::timestamp without time zone))
Buffers: shared hit=191
-> Index Scan using documents_document_pkey on documents_document documents_access__document_id_1 (cost=0.42..2.44 rows=1 width=9) (actual time=0.001..0.001 rows=1 loops=200)
Index Cond: (id = documents_access_1.document_id)
Filter: (((access_via_link)::text <> 'none'::text) OR ((documents_access_1.role)::text = ANY ('{view,edit}'::text[])))
Rows Removed by Filter: 0
Buffers: shared hit=800
Planning:
Buffers: shared hit=56
Planning Time: 1.569 ms
Execution Time: 157.171 ms
```
portal user
before https://explain.dalibo.com/plan/e1e755fg7bb26a21
after https://explain.dalibo.com/plan/hb5fa1d201ff164g
internal user with few documents access
before https://explain.dalibo.com/plan/f753bf2aa244dg63
after https://explain.dalibo.com/plan/538dg5ecb120ch84
internal user with *lots* of documents access
before https://explain.dalibo.com/plan/cf76h84537f7ge4a
after https://explain.dalibo.com/plan/45317a5e3168c5bcThis update resolves an issue preventing the correct export of balance sheet data in the Lu (Luxembourg) localization. The system now automatically includes a default start date (beginning of the fiscal year) in the XML file, ensuring accurate reporting. This prevents errors during the export process.
Original PR description
Steps to reproduce: - setup a LU company - go to balance sheet - export the xml file - validate the wizard -> Traceback, because the code expects the options to contain the date_from, which is no longer the case since 19.2 as the balance sheet has by default only a date_to. The solution is therefore to define it for the export to the beginning of the fiscal year.
This update corrects a technical issue in the UBL BIS3 generation process for Debit Notes. Previously, the system incorrectly used 'LegalMonetaryTotal' instead of the required 'RequestedMonetaryTotal' node, leading to errors in UBL file creation. This change ensures compliance with BIS3 standards for Debit Note UBL exports.
Original PR description
Problem --------- Debit note should have the node `RequestedMonetaryTotal` instead of `LegalMonetaryTotal`. Solution --------- Add a conditional depending on the document type. opw-6295897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270238
This update resolves an issue in the Data Recycle app where record IDs were incorrectly summed and displayed alongside group names, causing truncation and unreadability. The fix removes the unnecessary aggregation of record IDs, resulting in a cleaner and more informative display of grouped records.
Original PR description
## Issue In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="720" height="281" alt="115492" src="https://github.com/user-attachments/assets/567902af-b356-4a0a-8b1e-2ed101a2eba3" />
## Steps to reproduce
1. Install *Data Recycle* (`data_recycle`)
2. In Data Cleaning > Configuration > Recycle Records, create a new rule:
- Any name
- Model: *Contact*
- Filter: *Name contains G* (or anything else that matches some records)
4. Click the *Run Now* button in the upper left corner
5. In Data Cleaning > Recyle Records, group the records by any field (e.g., *Model*)
6. **The name of the group (Contact) is truncated, making it and the record count unreadable. This is due to the sum of Record ID being displayed in the same row, even though that information is irrelevant.**
## Cause
Similarly to related enterprise PR https://github.com/odoo/enterprise/pull/115492, the *Record ID* field of the `data_recycle.record` model uses the default `sum` aggregator.
https://github.com/odoo/odoo/blob/6de867f1c92bacedc0574b63e9e6a2a57fe805dd/addons/data_recycle/models/data_recycle_record.py#L17
related: https://github.com/odoo/enterprise/pull/115492
opw-6219824
Forward-Port-Of: odoo/odoo#265163This update resolves an issue in the Data Cleaning app where record IDs were incorrectly summed and displayed alongside group names, leading to truncated names and inaccurate counts. The fix removes the automatic summing of IDs in grouped list views, ensuring that group names and counts are displayed correctly.
Original PR description
## Issue In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="709" height="374" alt="6166623-before" src="https://github.com/user-attachments/assets/9d80b1ec-49c0-4b7f-8c6e-53846f9e433e" />
## Steps to reproduce
1. Install *Data Cleaning* (`data_cleaning`)
2. In Data Cleaning > Configuration > Field Cleaning, create a new rule (or edit an existing one):
- Any name
- Model: *Contact*
- Rule:
- Field to Clean: *Name (Contact)*
- Action: *Set Type Case* - Case: *All Uppercase*
4. Click the *Clean* button in the upper left corner
5. In Data Cleaning > Field Cleaning, group the records by any field (e.g., *Field*)
6. **The name of the group (_Name (Contact)_) is truncated, making it and the record count unreadable. This is due to the sum of _Record ID_ being displayed in the same row, even though that information is irrelevant.**
## Cause
The *Record ID* (`res_id`) field is an Integer field defined [here](https://github.com/odoo/enterprise/blob/3603afdd5c0d19c9276f3855156be4040ab5717d/data_cleaning/models/data_cleaning_record.py#L20). By default, Integer fields have the `sum` aggregator:
https://github.com/odoo/odoo/blob/681610c002a310f1c73fc2e5bec8d3dae27bc4a7/odoo/orm/fields_numeric.py#L17-L23
This causes the IDs to be summed up and appear in the group headers.
## After
<img width="740" height="370" alt="6166623-after" src="https://github.com/user-attachments/assets/a42d8f58-06dc-4308-8b6f-1ab09e8034f8" />
related: https://github.com/odoo/odoo/pull/265163
opw-6166623
Forward-Port-Of: odoo/enterprise#115492This update fixes an issue where product costs weren't consistently converted to the POS currency during product loading. Previously, product costs were stored in separate currencies, leading to potential inaccuracies in sales calculations. This change ensures all product costs are correctly converted, improving the reliability of pricing in the Point of Sale system.
Original PR description
When loading products in the POS, both the sale price and the cost were converted to the POS currency using `currency_id`. However a product stores its sale price and its cost in two potentially different currencies: `currency_id` (company currency, falling back to the main company) and `cost_currency_id` (company currency, falling back to the current company). opw-6297452 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269829
Code cleanup and technical improvements
This update enhances the Odoo system by making a key component, `fragment_to_query_string`, more flexible and reliable. It now allows other Odoo modules to use this functionality, improving code organization and reducing potential issues. The changes also include important JUC compliance improvements through documentation and testing.
Original PR description
## [MOV] odoo,auth_oauth: fragment_to_query_string The aim of this commit is to allow module unrelated to auth_oauth to import fragment_to_query_string. task-id: 6071808 ## [REF] odoo: JUC compliant fragment_to_query_string The aim of this commit is to make `fragment_to_query_string` JUC compliant by: - documenting the behavior - clarifying the code - reducing possible side effect - testing the behavior - add a route to be able to test it manually task-id: 6071808 Forward-Port-Of: odoo/odoo#270834
This update ensures that a critical function used in social media integrations is correctly referenced within Odoo. This change supports ongoing development and maintenance of the social media features, ensuring they continue to function reliably. It’s a routine update to maintain the stability of the system.
Original PR description
The aim of this commit is to keep referencing fragment_to_query_string correctly as it is moved into `http.py`. task-id: 6071808 Forward-Port-Of: odoo/enterprise#121019
15 changes
New functionality added to Odoo
This update adds support for several popular food delivery services – including Talabna, Mandoob, and DiDi Food – expanding Odoo's reach to new markets and catering to a wider range of customer preferences. The update also backports existing delivery provider integrations, ensuring continued functionality.
Original PR description
In this commit: - We are introducing new delivery providers like Talabna, Mandoob, Snoonu, DiDi Food and Zyada for different countries and backporting Radyes, ToYou, The Chefz, InstaShop and Smiles. Task-6263289,6263272,6263203,6263165,6310690 Forward-Port-Of: odoo/enterprise#119537
Enhancements to existing features
This update clarifies the process for adding handwritten signatures within the HTML editor. The wording has been changed from 'Insert your signature from Sign' to 'Insert your handwritten signature' for better user understanding and a more natural workflow. This improves the overall user experience.
Original PR description
Purpose of this PR: - Replace 'Insert your signature from Sign' with 'Insert your handwritten signature'. task-6217718 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
This update resolves an issue where loading demo data for the `l10n_in` module failed when installed without pre-existing demo data. The fix ensures that company IDs are correctly converted into the required format, allowing users to successfully load demo data from the Settings menu. This improves the user experience and ensures consistent demo data setup.
Original PR description
## Description When loading demo data from **Settings** after installing `l10n_in` without demo data, the `_install_demo` method receives company IDs instead of a `res.company` recordset. As a…
## Description When loading demo data from **Settings** after installing `l10n_in` without demo data, the `_install_demo` method receives company IDs instead of a `res.company` recordset. As a result, the following line crashes: ```python companies.filtered(...) ``` with: ```text AttributeError: 'int' object has no attribute 'filtered' ``` This PR ensures that the received company IDs are converted into a `res.company` recordset before being processed, allowing demo data to be loaded successfully from the Settings menu. ## Steps to Reproduce 1. Install `l10n_in` **without demo data**. 2. Navigate to **Settings**. 3. Click **Load Demo Data**. ## Current Behavior Demo data installation fails with: ```text AttributeError: 'int' object has no attribute 'filtered' ``` ## Expected Behavior Demo data should be installed successfully without raising any exception. ## Solution Convert the received company IDs into a `res.company` recordset when the argument passed to `_install_demo` is not already a recordset.
This update resolves an issue where mass email campaigns were inadvertently using users' personal email servers, causing delays and errors. The changes now ensure that personal servers are excluded from the selection process for mass mailings, preventing campaigns from getting stuck and improving reliability. This ensures consistent email sending functionality.
Original PR description
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few…
A personal outgoing mail server is an `ir.mail_server` that belongs to one user. The system only lets that user send through it. Mass mailings do not always respect this, which can cause a few problems: 1. Admins cannot duplicate a personal server. The copy keeps the same owner, and the rule that says one user can own only one server stops the save. 2. In *Email Marketing > Settings*, the "Dedicated Server" picker offers every server, even personal ones. If an admin picks a personal one, all campaigns get stuck. The cron job runs as Odoobot, the personal server rejects it, and the mailing stays in the queue. 3. When no dedicated server is set, the fallback selection can still land on a personal server (for example because its `from_filter` matches the sender). The cron sends through it and gets rejected. One commit per problem: 1. **mail**: duplicating a personal server now produces a copy with no owner. 2. **mass_mailing**: the picker in the settings hides personal servers. Setting an owner on a server that is already used for mass mailing now raises a clear error that names the campaign blocking the change. 3. **mass_mailing**: personal servers are skipped when the fallback selection runs, so only shared servers are considered. opw-6086077 Forward-Port-Of: odoo/odoo#261537
This update significantly speeds up appointment scheduling, particularly when managing multiple resources like tables in a restaurant. The change streamlines the process of checking resource availability, reducing load times by up to 70% for complex scenarios. This results in a faster and more responsive user experience.
Original PR description
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that…
In the current code, for each slot, and for each "available" resource, we check if the resource is available on the slot, based on availability values. Then, we check the remaining capacity of that resource. Also, linked resources information is added when computing the original resource remaining capacity. If many linked resources exist, this will be done several times and is not useful. This commit makes that loop disappear. We now check all resources at once in terms of availability, and linked resources that could be selected (in the appointment resources, in the slot resources (if any restricted resource)) at the same time. Then, the total capacity is the sum of the resource remaining capacity and the ones of available linked resources. Therefore, _slot_availability_is_resource_available is renamed to _slot_available_resources, as it now takes more than one resource and returns all resources among 'resources' that are valid on the slot, based on the availability_values, slot restrictions and booking lines. A noticeable difference is mainly seen when using many resources (and linked resources). For instance, a restaurant with a lot of small tables will have their slot availability check much shorter. BENCHMARK, LOCAL (time only, as number of requests does not change) Only appointment installed For a restaurant with - 10 tables of 2 - 5 tables of 2 linked, 2 times - 10 tables of 4 - 2 table of 2 - time then auto assign On loading /appointment/id: ~ 3.1s -> ~ 1.6s On selecting any number of people (1 to 10): [2s, 2.5s] -> [0.6s, 0.8s] Task-4144524 Forward-Port-Of: odoo/enterprise#107711
This update resolves an issue where appointment invitations weren't always sent correctly. The change ensures invitations are only sent when an appointment is in the 'booked' or 'request' status, preventing unnecessary emails and improving efficiency. This was originally identified and addressed in a related enterprise PR.
Original PR description
This PR adapts the code to fix the invitations at the appointments' update. See the enterprise PR to get more information about the issues. Enterprise PR: https://github.com/odoo/enterprise/pull/114304 Task-6139036 Forward-Port-Of: odoo/odoo#260073
This update ensures appointment invitations are only sent when an appointment is actually booked or requested, resolving previous issues where invitations were incorrectly triggered. It now correctly sends invitations to new attendees of booked appointments and ensures the correct status changes are logged, improving the reliability of appointment scheduling notifications.
Original PR description
This PR fix three issues related to the sending of the appointment invitations. Each one has its own commit: - Commit 1 sends invitations only if the event either "booked" or "request". Previously they were sent even if the appointment was cancelled. - Commit 2 prevents the sending of regular invitations and always sends appointment invitation to new attendees of existing booked appointments. - Commit 3 sent appointment invitations if the status of an existing event is set "request". It also add the status change in the log as it would have been if it was done at the creation. Community PR: https://github.com/odoo/odoo/pull/260073 Task-6139036 Forward-Port-Of: odoo/enterprise#114304
This update resolves an error that prevented users from sorting tasks by their planned dates within the project management portal. The fix ensures that the system correctly retrieves sort order information, preventing a 'KeyError' and improving the user experience. This change ensures reliable task sorting functionality.
Original PR description
Currently, an error occurs when a user sorts tasks by Planned Date. **Steps to reproduce:** - Install the `project_enterprise` module with demo data. - Go to Projects in the portal (`/my/projects`),…
Currently, an error occurs when a user sorts tasks by Planned Date. **Steps to reproduce:** - Install the `project_enterprise` module with demo data. - Go to Projects in the portal (`/my/projects`), open any `project`, and sort the tasks by `Planned Date`. KeyError: 'order' After a [recent change], the sort order is retrieved from searchbar sortings. When sorting by Planned Date, it attempts to access the order key from the corresponding sorting configuration [1]. However, the planned_date_begin entry does not define an order key [2], which raises error when it tries to access order. This commit ensures that the order key is added with its value for planned_date_begin in searchbar sorting. [recent change]: https://github.com/odoo/odoo/commit/8be5dacf9fbfe8c23b04c876994bea2ce7cbb89a [1]: https://github.com/odoo/odoo/blob/2ae9b57b86cd0bc4816ff8ec207564631baa8ad6/addons/project/controllers/portal.py#L424 [2]- https://github.com/odoo/enterprise/blob/9dd3a9b2c09a6d23a3f71d3e531edd6d78b30277/project_enterprise/controllers/portal.py#L8-L11 sentry-7556050938
This update resolves an error that occurred when users attempted to send SMS messages to website visitors. The fix updated the system to correctly access visitor phone numbers, ensuring the SMS functionality works as intended. This prevents a disruption in lead generation and communication.
Original PR description
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another…
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another `Form` block. - Configure the form action to `Create an Opportunity` and `save`. - Fill in the required fields, including phone number and `Submit` the form. - Go to `Website` > `Reporting` > `Visitors` and click the `SMS` button on the visitor record. `AttributeError: 'website.visitor' object has no attribute 'phone'` After [this commit], which removed the mobile field from res.partner along with all related views, then it was updated to access the phone number from the website visitor. When a user creates an opportunity through the website and then tries to send an sms from the corresponding visitor record, it raises an error [1] because it attempts to access the phone field on website.visitor. when an anonymous (non-logged-in) user creates an opportunity, clicking the sms button on the corresponding visitor record triggers error here [2]. This commit ensures that the correct mobile field is accessed from the website visitor. [this commit]: https://github.com/odoo/odoo/commit/6b820eb6fc6f782ba6a83d605d87b4a1dd2a87be [1]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L13 [2]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L20 sentry-7550340909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270118
This update corrects a technical issue where the UBL BIS3 format for Debit Notes was not fully compliant with the BIS3 standard. Specifically, the system was incorrectly using 'LegalMonetaryTotal' instead of the required 'RequestedMonetaryTotal' node. This change ensures accurate UBL BIS3 generation for Debit Notes, improving data consistency and compliance.
Original PR description
Problem --------- Debit note should have the node `RequestedMonetaryTotal` instead of `LegalMonetaryTotal`. Solution --------- Add a conditional depending on the document type. opw-6295897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270238
This update resolves an issue where milestone deadline dates would disappear from task views after navigating back or refreshing. The fix ensures that milestone deadlines are consistently displayed in task kanban views and task form views, regardless of user navigation.
Original PR description
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4.…
Steps to reproduce: 1. Open the Project application and open any project. 2. Filter the tasks by milestone (milestone deadlines appear as expected in the kanban view). 3. Open any task form view. 4. Click the browser's back button (or simply refresh the page while on the task kanban view). Issue: Milestone deadline dates disappear from the task Kanban cards and headers after navigating back or reloading. Why this happens: When hitting the browser back button or refreshing, the web client's router state recovery workflow executes (`loadRouterState` -> `loadState` -> `doAction` -> `_executeActWindowAction`). During this flow, `_getActionParams` checks if it can reuse the cached `lastAction`. However, due to a safety condition introduced in commit ab26f95893 to prevent embedded action showing across different projects, the router falls back to generating a fresh action request via `state.action`. This forces `_loadAction` to fetch the action definition from the database. Because the original base action window `act_project_project_2_project_task_all` lacks the `display_milestone_deadline` key inside its default context dictionary, the reloaded view is rendered without the flags required by the frontend to display milestone deadlines. opw-6283514 Forward-Port-Of: odoo/odoo#269781
This update corrects a visual issue in the Data Recycle app where grouping records resulted in incorrect record counts and truncated group names. The fix removes the unnecessary display of summed record IDs, improving the clarity and accuracy of grouped lists.
Original PR description
## Issue In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Recycle* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="720" height="281" alt="115492" src="https://github.com/user-attachments/assets/567902af-b356-4a0a-8b1e-2ed101a2eba3" />
## Steps to reproduce
1. Install *Data Recycle* (`data_recycle`)
2. In Data Cleaning > Configuration > Recycle Records, create a new rule:
- Any name
- Model: *Contact*
- Filter: *Name contains G* (or anything else that matches some records)
4. Click the *Run Now* button in the upper left corner
5. In Data Cleaning > Recyle Records, group the records by any field (e.g., *Model*)
6. **The name of the group (Contact) is truncated, making it and the record count unreadable. This is due to the sum of Record ID being displayed in the same row, even though that information is irrelevant.**
## Cause
Similarly to related enterprise PR https://github.com/odoo/enterprise/pull/115492, the *Record ID* field of the `data_recycle.record` model uses the default `sum` aggregator.
https://github.com/odoo/odoo/blob/6de867f1c92bacedc0574b63e9e6a2a57fe805dd/addons/data_recycle/models/data_recycle_record.py#L17
related: https://github.com/odoo/enterprise/pull/115492
opw-6219824
Forward-Port-Of: odoo/odoo#265163This update resolves an issue in the Data Cleaning app where grouping records resulted in the display of summed record IDs alongside group names, causing truncation and inaccurate counts. The fix removes the default 'sum' aggregator applied to integer fields, preventing this misleading display and ensuring accurate group counts.
Original PR description
## Issue In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which: 1. truncates the name and count of the groups 2. does…
## Issue
In the *Data Cleaning* app, when grouping records, the record IDs are summed up and appear right next to the name of each group, which:
1. truncates the name and count of the groups
2. does not make sense (summing up IDs is pointless)
<img width="709" height="374" alt="6166623-before" src="https://github.com/user-attachments/assets/9d80b1ec-49c0-4b7f-8c6e-53846f9e433e" />
## Steps to reproduce
1. Install *Data Cleaning* (`data_cleaning`)
2. In Data Cleaning > Configuration > Field Cleaning, create a new rule (or edit an existing one):
- Any name
- Model: *Contact*
- Rule:
- Field to Clean: *Name (Contact)*
- Action: *Set Type Case* - Case: *All Uppercase*
4. Click the *Clean* button in the upper left corner
5. In Data Cleaning > Field Cleaning, group the records by any field (e.g., *Field*)
6. **The name of the group (_Name (Contact)_) is truncated, making it and the record count unreadable. This is due to the sum of _Record ID_ being displayed in the same row, even though that information is irrelevant.**
## Cause
The *Record ID* (`res_id`) field is an Integer field defined [here](https://github.com/odoo/enterprise/blob/3603afdd5c0d19c9276f3855156be4040ab5717d/data_cleaning/models/data_cleaning_record.py#L20). By default, Integer fields have the `sum` aggregator:
https://github.com/odoo/odoo/blob/681610c002a310f1c73fc2e5bec8d3dae27bc4a7/odoo/orm/fields_numeric.py#L17-L23
This causes the IDs to be summed up and appear in the group headers.
## After
<img width="740" height="370" alt="6166623-after" src="https://github.com/user-attachments/assets/a42d8f58-06dc-4308-8b6f-1ab09e8034f8" />
related: https://github.com/odoo/odoo/pull/265163
opw-6166623
Forward-Port-Of: odoo/enterprise#115492This update fixes an issue where product costs weren't correctly converted to the POS currency. Previously, product costs were stored in separate currencies, leading to potential inaccuracies in pricing. This change ensures all product costs are accurately converted, improving the reliability of sales data in the Point of Sale system.
Original PR description
When loading products in the POS, both the sale price and the cost were converted to the POS currency using `currency_id`. However a product stores its sale price and its cost in two potentially different currencies: `currency_id` (company currency, falling back to the main company) and `cost_currency_id` (company currency, falling back to the current company). opw-6297452 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269829
This update prevents a traceback error that occurred when clicking the 'envelope' icon in the chatter, specifically during event registrations or follower additions. The issue stemmed from a missing `res_partner_id` field, which caused a conflict in notification filtering. This fix ensures the notification popover functions correctly regardless of whether a partner ID is present.
Original PR description
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When…
# How to reproduce - Create an Event registration - Add a follower - Click on the enveloppe icon next to the sender's name in the chatter # The problem A traceback appears # Cause of the issue When clicking on the enveloppe, we display the `message_notification_popover` that calls `isFollowerNotification` to filter follower notifications from other ones. This function compares the ids of the followers of the notification to it's res_partner_id : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/static/src/core/common/notification_model.js#L101-L105 But in our case res_partner_id is undefined because it is not a required field and it will not be set in the case of mass_mailing : https://github.com/odoo/odoo/blob/ee12a62407fa1c2dbca00d77dc6d5bd16eac1e43/addons/mail/models/mail_notification.py#L23-L27 opw-6178443 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#265263
4 changes
Resolved issues and error corrections
This update resolves an error that prevented users from sending SMS messages to website visitors. The fix corrects how the system accesses visitor phone numbers, ensuring compatibility with the latest website configuration changes. This ensures SMS functionality works as expected for all visitors.
Original PR description
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another…
Currently, an error occurs when a user tries to send an sms to a visitor. **Steps to Reproduce:** - Install `website_crm_sms` without demo data. - Go to `Website` > `Edit`, drag and drop another `Form` block. - Configure the form action to `Create an Opportunity` and `save`. - Fill in the required fields, including phone number and `Submit` the form. - Go to `Website` > `Reporting` > `Visitors` and click the `SMS` button on the visitor record. `AttributeError: 'website.visitor' object has no attribute 'phone'` After [this commit], which removed the mobile field from res.partner along with all related views, then it was updated to access the phone number from the website visitor. When a user creates an opportunity through the website and then tries to send an sms from the corresponding visitor record, it raises an error [1] because it attempts to access the phone field on website.visitor. when an anonymous (non-logged-in) user creates an opportunity, clicking the sms button on the corresponding visitor record triggers error here [2]. This commit ensures that the correct mobile field is accessed from the website visitor. [this commit]: https://github.com/odoo/odoo/commit/6b820eb6fc6f782ba6a83d605d87b4a1dd2a87be [1]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L13 [2]- https://github.com/odoo/odoo/blob/6a0e6443951053f8361e97f42e5e45c32bb73656/addons/website_crm_sms/models/website_visitor.py#L20 sentry-7550340909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270118
This update fixes a minor issue within the Odoo composer (email creation tool) that was causing text editing to behave unexpectedly. Specifically, it addressed a problem where inserting mentions created a formatting error, leading to incorrect cursor placement. Adding a special character ensures proper text editing functionality and a better user experience.
Original PR description
### Purpose of this PR: - Inserting a mention in the composer results in a paragraph ending with a bare `<a>` element and no trailing text node. This causes the browser to mishandle the End key, moving the caret to the start of the next paragraph instead of the end of the current line. - Fix by appending a \uFEFF (zero-width no-break space) text node. task-6295924 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#269699
This update corrects a technical issue in the UBL BIS3 generation process for Debit Notes. Currently, the system incorrectly used 'LegalMonetaryTotal' instead of the required 'RequestedMonetaryTotal' node, leading to errors in UBL file creation. This change ensures Debit Notes are formatted correctly for UBL BIS3 compliance, improving data accuracy and export functionality.
Original PR description
Problem --------- Debit note should have the node `RequestedMonetaryTotal` instead of `LegalMonetaryTotal`. Solution --------- Add a conditional depending on the document type. opw-6295897 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#270238
This update fixes an issue where the partner associated with an invoice was incorrectly overridden by the purchase order during UBL (Universal Business Language) XML imports. The change ensures the purchase order is the definitive source for partner information on invoices, improving data accuracy and consistency. This resolves a potential discrepancy between purchase and billing records.
Original PR description
Fix a bug where the partner of a bill is overriden by the PO matching The chosen logic here is to say that in the context of a purchase, the purchase order is the single source of truth to set the partner on a bill Steps to reproduce: - Create a partner with is_company = True - Create a contact type 'invoice' for this partner - Create a purchase order for the first partner - Import an XML (UBL) that matches this PO - You can see in the import logs that the partner was correctly found first, and then the PO matching override it to set the contact as the partner task-6289358 Forward-Port-Of: odoo/odoo#270780 Forward-Port-Of: odoo/odoo#269223
2 changes
Resolved issues and error corrections
This update resolves an issue where DIAN XML files for Point of Sale (PoS) payments were being rejected due to incorrect calculations of prepaid amounts. The fix combines payment amounts into a single tag, ensuring accurate data transmission to the DIAN and preventing errors related to negative payment lines.
Original PR description
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the…
**Steps to reproduce:** To test this, you will need an official DIAN setup, because this error comes from the response to our API call to the DIAN. - Setup the DIAN in a colombian company - Open the PoS - Order a product - Before paying, make the amount we are paying bigger than the amount due - We get an error response from the API, the error is saying that the total due does not match what we paid **Why the fix:** Currently, the xml is rejected because the sum of the **PaidAmount** in the **PrepaidPayment** tag is not equal to what we are trying to pay for. This is happening because to avoid the fact that we can not send a line with negative amount, we used the **abs()** function on the line amount to make it positive. The negative line comes from the fact that when we have a total due that is below the amount paid, we create a new payment line with a negative amount to balance it out. But as we can't send lines with negative amount, we needed to make it positive. This does not work, as the sum of the lines' amount will then be too much compared to what we are paying for, because instead of substracting it we will be adding it. To avoid this, we now group the amount in one single tag and send it this way. This ensures that the sent amount is correct and equals the amount due, and does not send a negative line. opw-6232575 Forward-Port-Of: odoo/enterprise#119255
This update fixes an issue where scanning unknown barcodes in the POS system didn't automatically open the product creation form. The fix removes a redundant API key check, ensuring the form opens correctly regardless of whether a barcode lookup API key is configured. This improves the user experience by streamlining the process of adding new products via barcode.
Original PR description
When scanning an unknown barcode in POS, the product creation form was never opened because `barcode_lookup()` was called with no barcode as an implicit API key check. Commit 0c8019a4aa7 ([FIX] product_barcodelookup: avoid crash on invalid image URLs) standardized `barcode_lookup_request()` to always
return a `requests.Response` object, removing the `{'authenticated': True}` dict it previously returned for HTTP 404 responses. As a result the JS check `response?.authenticated` was always falsy and the form never opened.
Fix: remove the API key check entirely. `allowProductCreation()` already gates on the user having product create rights, which is the only condition that matters. If a Barcode Lookup API key is configured the `_onchange_barcode` on the form will auto-fill product data; if not, the user can fill it in manually. Either way the form is always usable.
opw-629522123 changes
New functionality added to Odoo
This update introduces support for Nepal's unique fiscal year system, specifically the Bikram Samvat calendar. It allows for dynamic calculation and display of dates in the standard "day month_name, year" format, crucial for accurate financial reporting in Nepal. New fields and validation rules have been added to ensure correct date handling and prevent overlapping fiscal year ranges.
Original PR description
Inherit `account.fiscal.year` to add month lines One2many Add `l10n_np.account.fiscal.year.month.line` model with month name, start date and end date fields Add inline list view on fiscal year form for Nepal companies only
This update empowers appraisal administrators with the ability to create new appraisal plans within the Odoo Enterprise system. This enhancement streamlines the appraisal process and allows for greater flexibility in defining performance goals. The change was driven by task 6302703.
Original PR description
The appraisal admins should be able to create new appraisal plans. Task: 6302703
This update enhances the way our website displays appointment information to search engines and other online platforms. By adding Schema.org microdata, we're helping potential customers find our services more easily and accurately through search results. This improves visibility and potentially drives more leads.
This update introduces a new website form allowing customers to submit Field Service requests directly. Planning Managers can then review these requests and schedule interventions manually, bypassing the previous limitations of fixed booking times and payment requirements. The change also includes address autocomplete and improvements to ticket creation processes.
Original PR description
Field Service interventions can be booked online through the Appointment integration, but that flow has several limitations: - Interventions are booked at a fixed date and time without considering the customer's location. - Appointment types must enable upfront payment to create interventions. This commit: - Provides a public website form that lets customers submit Field Service requests. Submissions create a shift with no start date so Planning Managers can review the request and schedule the intervention manually. - Adds a "Service Requests" menu under Planning > Schedule listing slots with no planned date so managers can follow up with requesters. - Uses Google Places autocomplete on the address field when `website_address_autocomplete` is installed. task-6073523
This update adds the ability to associate contract dates with user groups within the HR payroll system. This allows for more precise tracking and reporting of employee contracts, improving payroll accuracy and compliance. The change impacts multiple localization modules.
Original PR description
Add the contract dates to the group_hr_user. Task: 6303353
Enhancements to existing features
This update improves the user experience by ensuring that clicking the budget icon on project overviews directly opens the budget action. Previously, this icon was inactive. This change streamlines the process of accessing project budgets, making it easier for users to manage financial planning.
Original PR description
**Before this commit:** - In the project overview, there's a button that indicates whether a budget has been set for a particular project. - Currently, clicking this button does not trigger any action. **After this commit:** - Clicking the budget icon on a project overview now opens the budget action. **Task-4841050**
This update adapts the SEPA Direct Debit payment process to support the new 'Pay on Invoice' option. This allows customers to choose to pay invoices directly, streamlining the payment process and offering greater flexibility. The changes were driven by community feedback and are designed to enhance the user experience.
Original PR description
See community commit for details. task-5149051
This update improves the live map experience by allowing users to easily focus on colleagues' locations and automatically including their live locations in Google Maps routing. This provides a more efficient and accurate way to coordinate with team members and plan routes.
Original PR description
# [IMP] web_map: allow inheritance of pin list for mobile view Prior to this commit, it was not possible for child modules to inherit from the pin list popover (i.e., the one used for the mobile view). # [IMP] planning_field_service: focus on user marker in live map In this commit, we add a button allowing users to focus on users' live location markers. The button is displayed only if the user is located (i.e., has a live location), and the view will zoom with an animation on the user pin. # [IMP] planning_field_service,web_map: google maps routing includes user location This commit adds users' live location as original addresses when opening the routing in Google Maps in the live map. task-6168733
This update introduces continuous production tracking for work orders, allowing workers to easily record completed quantities. The latest quantity recorded automatically updates the production quantity, speeding up the process. Enabling this feature ensures work orders become ready as soon as some quantities are completed, improving efficiency.
Original PR description
Allow workers to record the quantities completed on each workorder, the latest recorded quantity becomes the mo's producing quantity. Add a flag to enable continuous production (subsequent work orders will become ready as soon as some quantities are ready). See https://github.com/odoo/odoo/pull/267113 task: 6175830
This update adds AI-driven transcription to Odoo calls (VoIP and Discuss), improving meeting summaries and searchability. The new system processes call recordings in smaller chunks, preventing performance issues and ensuring reliable transcription, while also integrating with VoIP demo mode for testing.
Original PR description
This PR builds upon the Community PR (odoo/odoo#233836) by extending the call.artifact model with AI-powered transcription capabilities for both VoIP and Discuss calls. Rather than attempting to…
This PR builds upon the Community PR (odoo/odoo#233836) by extending the call.artifact model with AI-powered transcription capabilities for both VoIP and Discuss calls.
Rather than attempting to transcribe monolithic, multi-hour call recordings, this architecture processes chunked artifacts independently. This solves the 25MB payload limit of the LLM APIs and allows for granular error handling.
**Overview:**
- Gevent Orchestration (vs. Cron): Abandoning cron-based approach. Transcription is now orchestrated via a background gevent thread (action_transcribe_gevent). This provides immediate feedback post-call and prevents long-running I/O operations (LLM API calls) from hogging the Odoo cron workers.
- Safe 3-Phase Processing: To keep db connections short during the slow LLM API calls, the gevent orchestration uses a Claim → Process → Finalize pattern, committing the transaction between each step.
- Cloud Storage Architecture: Persistent call recordings are strictly offloaded to the cloud_storage module to prevent Odoo filestore bloat. However, transient STT audio chunks bypass this requirement, saving locally and deleting themselves immediately after successful transcription.
- VoIP Integration (voip_ai): Fully integrates the transcription flow into the VoIP softphone, including automated one-liner call summaries generated from the concatenated artifact transcripts.
- VoIP bonus -- demo, as a byproduct of this PR the demo for call was enriched with bying able to record and transcribe
(Note: Previous legacy recordings/transcriptions are migrated to call.artifact via odoo/upgrade#9521).
**Artifact Transcription Lifecycle:**
When an audio chunk is uploaded for transcription, it state machine to guarantee it is processed exactly once, with built-in retry logic for transient API failures.
```mermaid
stateDiagram-v2
[*] --> Pending : Chunk Uploaded (is_stt=True)
state "Pending" as Pending
state "Claimed (Leased)" as Claimed
state "Done" as Done
state "Error (Terminal)" as Error
Pending --> Claimed : action_transcribe_gevent (TX#1)
Claimed --> Pending : API Failed (Retries < Max)
Claimed --> Done : API Success (TX#3)
Claimed --> Error : API Failed (Retries >= Max)
Claimed --> Error : File too large / No media
Claimed --> Pending : Worker Crash (Lease Expires)
Done --> [*] : Media unlinked, Parent notified
Error --> [*] : Media unlinked, Parent notified
```
task-5153790This update adjusts the Odoo payroll accounting configuration to align with the latest Egyptian Chart of Accounts. This ensures that all payroll journal entries accurately reflect the correct accounts, complying with Egyptian tax regulations.
Original PR description
The Egyptian Chart of Accounts has been updated, so the payroll accounting configuration must be adjusted accordingly to ensure payroll journal entries use the correct accounts. Related PRs Community - https://github.com/odoo/odoo/pull/266614 Upgrade - https://github.com/odoo/upgrade/pull/10339
This update simplifies the process of tracking stock by vehicle within Field Service. Previously, configuring vehicle warehouses was hidden and difficult, but now a centralized dashboard provides easy access and management, streamlining operations at scale. The new system enforces data integrity to prevent errors and ensures accurate fleet assignments.
Original PR description
Since v14, tracking stock by vehicle required manually setting a 'default warehouse' hidden deep within individual user preferences. Because this field was completely invisible unless multi-warehouses were enabled, the feature was largely undiscoverable and extremely tedious to manage at scale. This commit solves the discoverability and configuration issues by introducing a centralized Vehicle Warehouses dashboard directly in the Field Service settings. Key impacts: - Adds a direct "Stock by Vehicle" setup link in the Field Service settings. - Introduces a dedicated list and mobile Kanban view to easily map specific warehouses (vehicles) to assigned technicians (planning users). - Enforces strict constraints to prevent duplicate fleet assignments and ensures warehouses and users remain strictly linked within the same company. Task: 6190476
This update removes an unnecessary abstraction layer in the SGK Hiring report process. The previous abstract model was deemed redundant as it was only used in one place, leading to a simpler and more maintainable codebase. This change improves efficiency and reduces complexity.
Original PR description
Previously, we had an SGK abstract model that was used by the SGK Hiring report. The idea was that we might extend its functionality to other models in the future, improving code readability and maintainability. However, it turns out that there is currently no benefit to having an abstract model, as it is only used in one place. Therefore, this change removes the unnecessary abstraction and keeps the implementation simpler. Task: TBD
This pull request makes minor improvements to the user experience within the MRP modules (mrp_plm, mrp_workorder, quality_mrp). Specifically, the 'Review Changes' button has been simplified for better clarity and the wording of the work order timer setting has been updated for improved understanding. These changes enhance usability and streamline workflows.
Original PR description
Minor UI tweaks for MRP submodules: * 'Review Changes' smart button renamed to simply 'Review' in PLM form view. * Reworded description for the WO timer setting. Built atop #112997. Task ID: [6152764](https://www.odoo.com/odoo/my-tasks/6152764)
This update enhances the map view by displaying resource avatars when routes are grouped by resources. This provides a clearer visual representation of the routes and makes it easier to identify associated resources within the map interface. This change improves usability and provides a more intuitive experience for users.
Original PR description
## [IMP] web_map: define template for routing information popup This commit defines the routing information popup as a template, allowing other modules to extend/modify it. ## [IMP] planning_field_service: show resource avatar on route popover In this commit, we add the resource's avatar to the routing popover in the map view. This only applies when the view is grouped by resources. task-6273760
This update enhances the layout of the MRP BOM line view by aligning the 'Bom Version' and 'Product Version' columns with their corresponding 'Final Product' and 'Bill of Material' counterparts. This change improves clarity and consistency for users reviewing BOM information, mirroring a previous update in the Odoo Community.
Original PR description
The 'Bom Version' and 'Product Version' columns positions are switched to match their 'Final Product' and 'Bill of Material' counterparts on the same view (see PR 262691 on Odoo Community). Task: 6113304
Resolved issues and error corrections
This update fixes an issue in the Belgian payroll calculations related to DMFA (termination) payments. Previously, the system incorrectly stopped calculating payments after a 3-month period, even with ongoing remuneration. This change ensures that payments continue as long as remuneration exists, preventing employees from being completely unenrolled with no payment during extended sickness periods. The update includes new tests to guarantee accurate calculations.
Original PR description
. Iterate as long as there is a remuneration on the dmfa period > 0, not stop to the previous period only. . The fix was made so if the remuneration on the dmfa period (3 months) is null, system will check the previous remuneration on the previous dmfa period, BUT, if we take a long sickness period on an employee, you can have people with 2 or 3 DMFA fully unenmployed with no remuneration at all . Add the corresponding tests task-6299792
This update adds a validation check to ensure employees have a defined work schedule (resource calendar and hours per week). This prevents issues with the DMFA process, ensuring accurate payroll calculations and data integrity. It's a necessary step to maintain the reliability of employee data within the HR module.
Original PR description
Added an @api.constrains check on resource_calendar_id and hours_per_week. Raises a translated ValidationError if both fields are left empty. Added validation since it's causing issue with DMFA. task-6296689
This update resolves an issue where sending NFC-e invoices would halt the POS synchronization process when IAP credits were exhausted. The change prevents the system from blocking POS updates, ensuring continued functionality even when IAP credit limits are reached. This improves reliability and prevents disruptions to sales operations.
Original PR description
When sending an NFC-e, tax calculation is done by calling Avatax through IAP. If the IAP account has no credits left, iap_jsonrpc() raises an InsufficientCreditError. opw-6290857 Forward-Port-Of: odoo/enterprise#120700
This update resolves a crash that occurred when users were manually correcting bank statement lines within the Odoo Enterprise system. The issue stemmed from a missing context setting during record creation, preventing the correct journal from being assigned. This fix ensures accurate journal assignments and prevents data modification errors.
Original PR description
When the manual correction tool was used to fill in the lines, we weren't passing the active context when creating the new records. In the case of bank statements, it could be an issue as the `default_journal_id` key is expected to be present to set the correct journal on the newly created bank statement line. Without this key in the context, it would default to the first journal with a valid type (see function `_search_default_journal`). If the journal found this way didn't match the current journal, a crash would occur when modifying the newly created lines. opw-[6294117](https://www.odoo.com/odoo/unassigned-tasks/6294117) Forward-Port-Of: odoo/enterprise#121032 Forward-Port-Of: odoo/enterprise#120745
This update resolves an issue where manually created timesheets weren't correctly linked to the associated Sales Order Item. The fix ensures the Sales Order Item information is properly inherited during timesheet creation, improving data accuracy and streamlining the timesheet process. This prevents errors when recording time against sales orders.
Original PR description
### Issue: When manually creating a timesheet from a planning shift's smart button, the Sales Order Item is not inherited. ### Cause: The `planning_slot_id` was missing from the timesheet list view. As a result, the `default_planning_slot_id` passed in the context was dropped during the creation of the new record, preventing us from linking the correct SO line. Solution: Added `planning_slot_id` as `column_invisible="True"` in the timesheet list view so the context default is retained. task-6229397
This update fixes an issue where the Gantt chart popover displayed only start and end dates for project tasks. The change ensures the popover correctly uses the card view, providing richer task details. This improves the user experience when viewing project timelines.
Original PR description
Since odoo/odoo#114328, the kanban view of the action isn't used as gantt popover by default if no popover is defined in the gantt view arch. As a consequence, on the project sharing task gantt view, the popover was the default, basic one which displays only the start and end dates. This commit restores the previous behavior by explictly set on the gantt view the id of the card view to used inside the popover. To achieve this, it was necessary to extract that card view out of the kanban. Followup of task~5262907
This update resolves a minor issue where deleting an Obox didn't properly remove associated queue records, leading to potential data inconsistencies. It also corrects a bug where duplicate device identifiers caused incorrect device updates. This ensures accurate device tracking and management within the Obox system.
Original PR description
This commit fixes two minor bugs: 1. Deleting an Obox record does not delete the queue records associated with it. If you link an Obox with the same serial again, the old queue actions are linked to with the smart button, but don't actually link to the new Obox record. 2. If an Obox discovers a device with the same identifier as an existing device linked to a different Obox, the device is not added, instead updating the other device.
7 changes
Enhancements to existing features
This update adds debtor and creditor information to the data sent to payment processors (Powens and Saltedge) when initiating payments. This enhancement ensures accurate payment processing and compliance with payment gateway requirements.
Original PR description
In order to be able to initiate payments using Powens and Saltedge, we need to include debtor information in the payload sent to Odoofin. This commit adds the necessary fields and updates the tests accordingly. Task ID: 5977148, 6095729
Resolved issues and error corrections
This update resolves an issue where tooltips in the spreadsheet edition's list autofill feature were displaying error messages instead of correct information when the list data wasn't yet ready. The fix ensures that tooltips display the correct data, improving the user experience and preventing misleading notifications.
Original PR description
The getter `getTooltipListFormula` would return the result of `getListHeaderValue` as the content of the tooltip, but this returned a loading error instead of a string if the list was not ready yet. Task: [6289944](https://www.odoo.com/web#id=6289944&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form)
This update adds a new testing option to our spreadsheet functionality. It allows developers to quickly test scenarios where the list data isn't immediately available, ensuring the spreadsheet handles loading delays gracefully. This improves the reliability and stability of the spreadsheet feature.
Original PR description
Added the parameter `skipWaitForDataLoaded` to `createSpreadsheetWithList` to test what happens when the list is not ready yet. Task: [6289944](https://www.odoo.com/odoo/2328/tasks/6289944) 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
This update ensures that database indexes automatically update when a field's index type changes (e.g., from btree to trigram). Previously, upgrades silently ignored these changes, leading to outdated indexes and potential performance issues. Now, the system proactively rebuilds indexes to match the field's requirements, maintaining optimal database performance.
Original PR description
Description of the issue/feature this PR addresses: `Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates…
Description of the issue/feature this PR addresses:
`Registry.check_indexes` derives a column index's name as `<table>__<column>_index`, which does **not** encode the access method, and only creates the index when no index of that name already exists. It never inspects the access method of an existing index.
As a consequence, changing a field's `index=` kind on an **already-indexed** column is silently ignored on existing databases. For example `account.move.name` was changed from a plain btree index to `index='trigram'`:
```python
name = fields.Char(
...
index='trigram',
)
```
On a fresh database this creates the expected GIN/trigram index. On any database that already had the btree index, the old btree index keeps its name, so `check_indexes` finds the name present and does nothing. The `(=)ilike` searches the trigram index was meant to accelerate keep falling back to sequential scans, with no error or warning.
Current behavior before PR:
### Steps to reproduce
1. Install a module on an existing DB while a `Char` field is `index=True` (btree).
2. Change the field to `index='trigram'` and upgrade the module.
3. `\d <table>` in psql — the index is still `USING btree`, not `USING gin`.
Desired behavior after PR is merged:
`check_indexes` now also reads each existing index's access method (`pg_am.amname`). When the method no longer matches what the field expects (`gin` for trigram, `btree` otherwise), the stale index is dropped and recreated. The drop is issued inside the **same savepoint** as the recreate, so a failed rebuild (e.g. a lock timeout) rolls the drop back and never leaves the column without an index.
Scope: only the access method is reconciled. A change that alters solely the partial predicate (`btree` -> `btree_not_null`) keeps the same method and is intentionally left untouched.
### Notes
- This extends the existing index-management logic in place and keeps the current "keep unexpected index" behaviour for fields that dropped `index=` entirely; only fields that still want an index, of a different method, are rebuilt.
- Trigram rebuilds still require the `pg_trgm` extension; without it the GIN index is skipped exactly as before (`self.has_trigram` guard).
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update corrects a requirement in the Nemhandel integration for Danish UBL invoices. Specifically, it adds a 'TaxCategory' node to the 'AllowanceCharge' element, which is now necessary to meet UBL formatting standards. This ensures proper invoice processing with Nemhandel and avoids potential errors.
Original PR description
Add the TaxCategory node in AllowanceCharge node as it's a requirement for some UBL format. It has been spoted with Nemhandel, as it requires a single tax category in the AllowanceCharge. no-task
This update resolves an issue where selling combos through the Point of Sale (PoS) system triggered a warning and prevented order validation due to eTIMS registration requirements. The fix ensures that individual combo items are correctly registered, allowing combo sales to proceed smoothly without these blocking errors. This improves the PoS experience for Kenyan businesses using eTIMS.
Original PR description
Steps to reproduce ------------------ 1. Install l10n_ke_edi_oscu_pos. 2. Select the Kenyan company. 3. Enable eTIMS on the PoS. 4. Register the products inside a combo, but not the combo itself. 5. Sell the combo in the PoS. Observation ----------- We see a warning that the combo must be registered to eTIMS, and the order can't be validated. What's happening ---------------- In the PoS a combo adds a 0 price parent line for the combo product, but the combo is not a real item to send to eTIMS, only the products inside it are, and (as per step 4) the combo is not registered. `checkEtimsFields` sees the combo as not registered, so it raises the warning in `showUnregisteredProductsWarning` and blocks the payment in `validateOrder`. Fix --- In the backend, we skip sending the parent combo line to eTIMS, and on the frontend, we make the combo parent line not need eTIMS registration, so the warning and the block don't apply to it. opw-6253306
This update resolves a problem where Italian fiscal printers would stop printing POS orders due to unsupported characters in product or payment method names. The fix replaces these characters with spaces, ensuring complete and accurate printing, as defined by EPSON's official documentation.
Original PR description
Steps to reproduce: - Setup an Italian fiscal printer - Modify the name of a product to use the non-blocking space character "\ "; - In the POS, create an order with the product. Error: the fiscal device will stop midway in the printing process and return an incomplete response to the frontend. The issue can also be reproduce if the character is included in the payment method name or the POS config name. Solution: When formating the xml command, replace all non-supported character by a space character. The non-supported character list is provided by the official [EPSON fiscal printer documentation](https://support.epson.net/setupnavi/?PINF=bsmanual&OSC=WS&LG2=EN&MKN=FP-90III%20RT) in the document "ePOS Fiscal Print Solution Development Guide". Other: Rename the file "dispaly_text.xml" to "display_text.xml". [opw-6244089](https://www.odoo.com/odoo/project/49/tasks/6244089)
3 changes
Resolved issues and error corrections
This update ensures GIF functionality in Odoo continues to work smoothly. The previous Tenor GIF API key is being replaced with a Klipy GIF API key due to the Tenor API's planned shutdown on June 30, 2026. Users will need to update their API key settings to ensure GIF sharing remains operational.
Original PR description
Tenor API will be terminated on June 30, 2026: https://developers.google.com/tenor/guides/quickstart This commit makes the Tenor API key input settings use a Klipy GIF API key instead of a Tenor GIF API key. To keep GIF working after this commit, the API key must necessarily be changed to a Klipy GIF API key, as the old Tenor API key would be considered as an invalid Klipy API key. Task-5491965 Upgrade: https://github.com/odoo/upgrade/pull/10516
This update resolves an issue in the 17.0 version of Odoo where users couldn't delete soda mapping records, leading to data management problems. The fix allows users to unlink these records, providing the necessary flexibility to correct errors and maintain accurate accounting data. This improves usability and prevents data blockage.
Original PR description
**PROBLEM** It's impossible to delete soda mapping in 17.0. So if you mess the mapping, you can't do anything about it. **STEP TO REPRODUCE** 1. Install l10n_be_codabox. 2. Select the belgium company, and goes to configurations/accounting. 3. Click on open soda mapping, create a new mapping line. 4. There is no way to delete it. opw-6293829
This update resolves an issue where E-Way Bill amounts were incorrectly calculated when sales prices included tax. The fix ensures that tax-included prices are properly processed, preventing double tax calculations and ensuring accurate E-Way Bill generation. This impacts sales orders with 'Tax Included' settings.
Original PR description
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create…
`*` = `ewaybill_Stock, sale_stock, purchase_stock` **Steps to reproduce:** * Install `l10n_in_ewabill_stock` and `l10n_in_sale_Stock`. * Set the Default Tax Price Setting to "Tax Included". * Create a Sales Order (e.g. unit price 300, qty 600, 18% GST) and confirm the Delivery Challan/Delivery Order. * Generate an E-Way Bill from the Delivery Challan. **Observed behavior:** * The Taxable Amount and Total Invoice Amount are displayed incorrectly in the generated E-Way Bill, including both the printed document and the JSON. * The `ewaybill_price_unit` shows the tax-excluded price (e.g. 254.24) instead of the original tax-included price (300), leading to a double tax exclusion when `compute_all` processes it. **Cause:** * `_l10n_in_get_product_price_unit` in both `l10n_in_sale_stock` and `l10n_in_purchase_stock` unconditionally used `price_subtotal / qty` to compute the E-Way Bill price unit. `price_subtotal` is always tax-excluded, so for tax-included prices, the tax was already stripped. * `_l10n_in_tax_details_by_stock_move` then passed this already tax-excluded price to `compute_all` with taxes that have `price_include=True`, causing `compute_all` to strip the tax a second time (e.g. 254.24 / 1.18 = 215.46 instead of the correct 254.24). **Fix:** * Check whether any of the line's taxes have `price_include` set. If so, use `price_total / qty` (which preserves the tax-included price) so that `compute_all` can correctly extract the tax. Otherwise, continue using `price_subtotal / qty` as before. opw-6273101