Daily updates from Odoo
Thursday, November 20, 2025
196 changes
20 changes
Resolved issues and error corrections
The Point of Sale now shows the product configurator when a product includes a free-text option, even if there is only one selectable value. This lets staff enter the required custom text instead of being blocked by a missing input field.
Original PR description
**Steps to reproduce:** - Make a new product, make a single variant with a single value for it - The variant value should have the Free Text checkbox enabled - Go to PoS, click on said product - The product configurator will not be displayed, so there is no way to write on this Free Text field **Why the fix:** Before this commit, we did not display the product configurator if all variant attributes were single choice, because it did not make sense to show it just for the user to click on confirm. But this did not account for the fact that if a Free Text option is enabled, we should still display it, so that the user can write whatever they want on it, even if it is the only option available. We now display the product configurator in all cases where a Free Text field is present, as we need the customer to be able to fill it, even if it is the only available option. opw-5133743
This change adds automated coverage for @mention suggestions in channels restricted to a specific group. It helps ensure people only see the right suggestions in these channels, reducing the chance of incorrect or confusing mentions.
Original PR description
This commit adds a test for mention suggestions in group-restricted channels (`group_public_id`). task-5258925 Forward-Port-Of: odoo/odoo#235478
This change fixes an issue where the message composer could fail while loading suggestions if no message was attached yet. It makes the feature more reliable and prevents an internal error from blocking the user experience.
Original PR description
This commit solves a runbot issue created by the debounced nature of the suggestion fetch. A composer could not have a message associated with it and was therefore failing to find the related thread. Now, the thread is set to undefined in that case since we do not need the result anyway. fixes-runbot-230311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236262
When a vendor bill email contains several attachments, Odoo now avoids creating additional bills unless the attachments are actually useful. This reduces clutter in the database and helps avoid unnecessary document processing costs.
Original PR description
Steps to reproduce: - Set up email alias for Vendor Bill journal - Send email with N images alias Issue: <N> Bills are created, in each one we will attempt to extract the image content to enrich the bill. Analysis: This occurs because we split the attachment list into several groups, each one creating a new invoice (except the first). However we don't take into account if the attachments are actually meaningful. In many cases this behavior will pollute the database and waste iap credits. This commit proposed to evaluate if in each group there is at least a meaningful attachment before creating/extending an invoice opw-5076315 [Ticket link](https://www.odoo.com/odoo/project/49/tasks/5076315)
Timesheet totals shown on helpdesk team pages were sometimes displayed with the wrong unit conversion, especially when the system was set to Days/Half-days. This fix restores the correct calculation so users see accurate totals, such as 2.5 days instead of 160 days.
Original PR description
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4.…
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4. Open the team’s settings and observe the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the team’s settings and observe the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------ After commit d23ca81, the UoM model was restructured, changing how conversions between hours and days are computed. The field `factor_inv`, previously used in the computation of total_timesheet_time, was removed. Earlier, `factor_inv` handled this conversion correctly. After its removal, the computation now directly uses factor, which leads to incorrect values when converting to days. https://github.com/odoo/enterprise/blob/92bb923ffe185b7744adeadcc8f2972f9a64effb/helpdesk_timesheet/models/helpdesk_team.py#L32-L36 For ex: Consider unit_amount = 20 minutes: **Before** Case 1: Encoding method = Hours/Minutes (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 1 = 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 8 = 160 Days --> INCORRECT **After** Encoding method = Days/Half-days (unit_amount_sum * (1.0 if helpdesk_ticket.encode_uom_in_days else product_uom_factor)) / uom_team.factor (20 * 1) / 8 = 2.5 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. **NOTE:** Before this change, when the user opened the timesheet sublist view in debug mode and clicked the View button, it opened the default form view of the `account.analytic.line` model instead of the intended timesheet form view. This allowed editing of the Unit of Measure (product_uom_id) field also. To prevent this, the form view reference has been explicitly specified, similar to the one used in the [Project module](https://github.com/odoo/odoo/blob/3f23bd9723d9065f17c1960d185d67a0a809a889/addons/hr_timesheet/views/project_task_views.xml#L41). Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related community PR: https://github.com/odoo/odoo/pull/233803 Forward-Port-Of: odoo/enterprise#98545
The project dashboard now shows the correct timesheet total when timesheets are entered in days or half-days. This fixes a display error that could make the stat button show much larger values than expected, helping users trust the numbers they see.
Original PR description
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard…
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard and check the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the project dashboard and check the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------- After this 28b69da, UoM model got restructured and the conversion logic between hours and days changed. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L137-L143 The `total_timesheet_time` value is now already stored in the final unit (e.g., days). The subsequent division in `_get_stat_buttons()` was a redundant **double conversion**, resulting in incorrect display. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L231-L234 **Before** Case 1: Encoding method = Hours/Minutes Consider allocated_hours = 80 Hours, total_timesheet_time = 20 Hours Then: uom_ratio = 1/1 => 1 allocated = 80/1 => 80 Hours effective = 20/1 => 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days Consider allocated_hours = 80 Hours, total_timesheet_time = 2 Days (already in days — no conversion needed, but the system incorrectly tries to convert it) Then: uom_ratio = 1/8 => 0.125 allocated = 80/.125 => 640 Days effective = 2/0.125 => 16 Days --> INCORRECT **After** Consider allocated_hours = 80 Hours (needs conversion to days as per encoding method) and total_timesheet_time = 2 Days (already in days, no conversion). Then: uom_ratio = 1/8 => 0.125 allocated = 80*.125 => 10 Days effective = 2 => 2 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related enterprise PR: https://github.com/odoo/enterprise/pull/98545 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233803
This fix prevents calendar event titles from being cut off in day view, especially on mobile devices. Users can now read the full event name at a glance, making it easier to review what needs to be done.
Original PR description
Before this commit, when the user goes to a calendar view in day to check what he have to do. He cannot see the event title properly in his mobile phone since the title is truncated. This commit makes sure the event title is not truncated to clearly see the whole event title. Before the fix: <img width="1172" height="802" alt="image" src="https://github.com/user-attachments/assets/f85a4a03-89a3-48c8-bda7-38e72854ce1f" /> After the fix: <img width="1179" height="808" alt="image" src="https://github.com/user-attachments/assets/7b0b31ba-10f5-412b-837b-8399c78c5bac" /> Forward-Port-Of: odoo/odoo#235823
This change prevents an error from appearing in Documents when a linked CRM record has been deleted. The system now correctly marks the related document as having no source record, so users can open Documents normally without a traceback.
Original PR description
Steps to reproduce: - Install crm and documents - Go to CRM → Activity Types - Set a folder in the Upload Document activity - Create a CRM lead and schedule an upload document activity - Delete the created lead - Open the Documents module Issue: - A traceback occurs because web_read tries to access values_by_id[record.id], as the upload request document remains in the database after its related activity is deleted. Solution: - fix the recompute of res_name and set it to False, avoiding MissingError opw-5080182 Forward-Port-Of: odoo/enterprise#97461
This update makes the Black Box payment device handling more resilient by retrying when the device returns an invalid response or no valid acknowledgment. It also aligns the timeout behavior with the documented limit, helping reduce payment interruptions at the point of sale.
Original PR description
Following documentation, max timeout should be 1.5s and we should retry 3 times on every bb NACK/invalid data. Forward-Port-Of: odoo/enterprise#99911 Forward-Port-Of: odoo/enterprise#99705
The website now hides mega menu links when their content is not available to the current visitor, instead of showing empty dropdowns. This makes the navigation cleaner on both desktop and mobile and avoids confusing users with menu items they cannot use.
Original PR description
Before this commit, when setting the mega menu content visibility, the navbar link would still appear even if the user does not have access to the mega menu content. This commit hides the navbar link for the mega menu in the mobile and desktop view when the user does not have access to the mega menu content, in order to prevent unnecessary elements in the navbar. Steps to reproduce the bug: - Add a mega menu element in the navbar - Open the mega menu - Set the mega menu content visibility to conditional (logged in) - Open the website while logged out (The mega menu link is here but the content is not displayed. However, the dropdown is still opened but it is empty.) task-3992066 Forward-Port-Of: odoo/odoo#235516 Forward-Port-Of: odoo/odoo#179454
This fix ensures POS order costs are calculated correctly when a product has variants and its Bill of Materials includes lines that apply only to specific variant values. As a result, each sold variant now reflects the right cost, avoiding incorrect margins and reporting.
Original PR description
When you create a product with atleast one variant that has 2 value, and create a BoM for this product that has 2 lines with each line having one of the two values, then create a POS order with one…
When you create a product with atleast one variant that has 2 value, and create a BoM for this product that has 2 lines with each line having one of the two values, then create a POS order with one unit of each variant, the cost of the first line not correctly computed. Steps to reproduce: ------------------- * Create a prodcut P with one attribute A that has two values A1 and A2 * Create a product C with no attribute and a cost of 10$ * Create a BoM for P with two lines: - Line 1: product C, quantity 1, only for attribute value A1 - Line 2: product C, quantity 2, only for attribute value A2 * Open a PoS session * Add Product P with attribute value A1 to the order * Add Product P with attribute value A2 to the order * Validate the order and close the session * Go to the order and check the cost of each line > Observation: The cost are not correct, they should be 10$ and 20$ Why the fix: ------------ Before this fix we were not taking the `bom_product_template_attribute_value_ids` into account when filtering the stock moves to consider for the cost computation. This value represent the attribute values that the product must have for this BoM line to be considered. opw-4765234 Forward-Port-Of: odoo/odoo#235502 Forward-Port-Of: odoo/odoo#225014
Updated the LinkedIn API header version used by the social LinkedIn integration. This was needed because the previous API version was retired, helping keep LinkedIn connections working without interruption.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
Fixed an error that could prevent non-admin employees from using the Purchase Order Suggest wizard. Regular purchase users can now complete the suggestion flow without being blocked by access restrictions, improving day-to-day purchasing operations.
Original PR description
**Issue:** Non-admin users get an AccessError as follows ```doesn't have 'create' access to: - Default Values, Based on (Purchase Order Suggest) (ir.default: 45)... ``` when using the Purchase Order…
**Issue:** Non-admin users get an AccessError as follows ```doesn't have 'create' access to: - Default Values, Based on (Purchase Order Suggest) (ir.default: 45)... ``` when using the Purchase Order Suggest wizard. **Cause:** The `ir_default_user_rule` record rule restricts non-admin users to only create/modify ir.default records where `user_id = user.id` However, in `_save_values_for_vendor` method: https://github.com/odoo/odoo/blob/6b8a8196c63275eead6709bb20002df0be12a059/addons/purchase_stock/wizard/purchase_order_suggest.py#L199-L204 `ir.default.set()` is called without setting the `user_id` parameter, which defaults to an attempt to create a global default: what only admins can do. **Steps to reproduce:** - create a non-admin user with purchase user permissions. - log in as that user and create a Purchase Order - add products to the catalog and click "Suggest. - configure suggest parameters and click "Compute" (Note: compute is only enabled when estimated_price > 0) An AccessError occurs opw-5076647 Forward-Port-Of: odoo/odoo#227643
This change fixes a website editing issue where shape previews could stay stuck after the mouse moved away. It ensures the image returns to its original look correctly, so hover-based image options like shapes and filters behave as expected.
Original PR description
After hover effect has been added back in this [commit], we could see an issue when we had a hover effect and tried to preview a shape. Steps to see the issue: - Open website and start editing - Drop…
After hover effect has been added back in this [commit], we could see an issue when we had a hover effect and tried to preview a shape. Steps to see the issue: - Open website and start editing - Drop a text-image snippet onto the page. - Then add a hover effect to the snippet image. - Open the image shape selector and hover over the shapes. => Bug: the preview is broken; when the mouse leaves a shape, the original shape is not reset. Same issue with other options when there is a hover effect on an image (e.g. "image Filter"). Current flow is: We are previewing shape -> img src is changed -> `originalImgSrc` in `ImageShapeHoverEffect` interaction is changed -> we revert preview -> img src is reverted, but MutationObserver doesn't change `originalImgSrc` immediately, and when reverting a step, we stop the interaction -> destroy is called and image source is set to `originalImgSrc`, but it is the old one with a shape. We want to update the `src` only if it is currently the one that we set as hovering. [commit]: https://github.com/odoo/odoo/commit/80b5db99a3c26c3dd4fb5c55e04b8813dddb5b8d task-5207382
This change reverses a recent update to how journal items are shown so that adding new lines to accounting entries works correctly again. It fixes an issue that could prevent debit and credit amounts from being computed properly when users edit entries.
Original PR description
This reverts commit 6ed1e43b3f7d53c6a45fe24a1c68f8386e6adf8e. The commit is reverted because the `journal_line_ids` field is causing issues with onchange methods that rely on cached values. Specifically, the automatic computation of `debit`/`credit` when adding new lines to a journal entry was failing. While `journal_line_ids` (as a subset of `line_ids`) works correctly when the data is stored in the database, its absence during an onchange computation (which relies solely on cache) led to incorrect behavior. In stable versions, `journal_line_ids` is: * Kept but deprecated. * Made non-exportable. The field will be removed in `master`. task-5241650 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
A recent change that hid sections and notes in journal item tabs has been rolled back because it interfered with how new journal lines are calculated. This restores the expected automatic debit and credit updates when users add lines to an entry.
Original PR description
This reverts commit 17d0e67106a30a46d608331680e5094dbc44e2e0. The commit is reverted because the `journal_line_ids` field is causing issues with onchange methods that rely on cached values. Specifically, the automatic computation of `debit`/`credit` when adding new lines to a journal entry was failing. While `journal_line_ids` (as a subset of `line_ids`) works correctly when the data is stored in the database, its absence during an onchange computation (which relies solely on cache) led to incorrect behavior. no-task
Website card images no longer show unwanted white borders when a hover animation is applied. This keeps the image filling its container correctly and improves the visual quality of edited website pages.
Original PR description
Step to reproduce: 1. Open website 2. Click edit button and drop s_three_columns snippet 3. Click image and change animation option into hover 4. Some extra white space shown. Before this commit: Applying a hover animation on card images caused the `object-fit` property to unintentionally switch from `cover` to `contain`, resulting in visible white borders around the image.This happened because of the `geo_square` shape, which is automatically injected when a hover effect is applied and no user shape is chosen. This behavior was intentionally introduced in PR [1]. After this commit: Now cropped images use object-fit: contain to preserve the visible properly. and after stretch option apply it can take cover of this container. so his ensures the image fully covers its container without leaving any white gaps. [1]:https://github.com/odoo/odoo/pull/119197 task:4875770 Forward-Port-Of: odoo/odoo#215766
Opening the shop floor app from a Manufacturing Order now shows the correct work center for that order, instead of possibly reopening the last work center used by the operator. This prevents users from landing on the wrong screen and makes it easier to see and manage the current order from the smart button.
Original PR description
Opening shop floor from MO smartbutton activates the WC "Overview". Subsequent opening of shopfloor app will also land on WC "Overview". Also removes an 'undefined' part of local storage key. BEFORE:…
Opening shop floor from MO smartbutton activates the WC "Overview". Subsequent opening of shopfloor app will also land on WC "Overview". Also removes an 'undefined' part of local storage key. BEFORE: Due to an oversight during this fix odoo/enterprise#93553, opening shop floor from MO smartbutton selects the WC from local storage (ie last clicked by user), with a filter for the current MO. (ie. when clicking Shopfloor smartbutton on an MO we can land on the wrong WC) NOW: Opening shop floor from MO smartbutton selects the WC "All MO" with a filter for the current MO. If we close shopfloor and come back to the shop floor app we land back on the "All MO" WC, which is the intended behaviour. Note: I did not rewrite tests I did here: https://github.com/odoo/enterprise/pull/93553/files#diff-2aa7dbd54334d280c72d91b7d472077aaae9af017408f1b0d71150bb16a022f4 as the setup is quite different in 18.0 (no access to the required stepUtils and the tour flow is quite different) task#4629641 Forward-Port-Of: odoo/enterprise#99855 Forward-Port-Of: odoo/enterprise#93841
This update prevents an error when a helpdesk ticket is moved to Done or Canceled in a team that has no working hours configured. It ensures the closing process only uses the working-hours logic when that setting is actually present, avoiding an unexpected traceback for users.
Original PR description
> **The issue:** When you go to a helpdesk's team settings -> SLA Policies -> Working hours, set the working hours to empty and then disable SLA Policies and save. After that if you try to move a ticket in the same team to done or canceled you will receive an exception. **Cause:** The part of the code causing the issue is supposed to only run if a Working Hours policy is set. **Fix:** Changed the section of the code to only run when Working Hours is set. opw-5120962 > Forward-Port-Of: odoo/enterprise#98889 Forward-Port-Of: odoo/enterprise#96546
This update prevents an error when opening older Point of Sale refund orders created from multiple original orders. It ensures upgraded databases keep working correctly and avoids interruptions during upgrade checks.
Original PR description
In saas~17.1, the field `refunded_order_id` was changed from a Many2Many to a Many2One, as refunding lines from different orders with the same order was no longer possible. The problem is that there were no changes applied to the existing data to account for this, so databases with those kind of refunds will trigger an error when the field is computed: ``` ValueError: Wrong value for pos.order.refunded_order_id ``` This behaviour can also break upgrades if the error happens during the mock crawl test after the upgrade. To reproduce: - In 17, create an order refunding products from different orders. - Upgrade to 18. - Try to view the refunding order. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224515 Forward-Port-Of: odoo/odoo#221355
17 changes
New functionality added to Odoo
This update adds support for carrying customer and checkout information from the website store into Taiwan e-invoice creation. It helps ensure invoice details are captured more accurately for online sales, reducing manual correction and improving compliance.
Original PR description
This module adds extra functions on the website sale for l10n_tw_edi_ecpay, passing values from e-commerce to invoice for creating Taiwan E-invoice task-5122489 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236288 Forward-Port-Of: odoo/odoo#228989
Enhancements to existing features
This update makes automatic database field conversion simpler and more predictable. It avoids unnecessary recalculation during upgrades, which should reduce upgrade time and prevent avoidable slowdowns.
Original PR description
The auto column conversion should be limited to simple and intuitive use cases. It shouldn't trigger the slow ORM recomputation if the field is computed. We always expect an upgrade script to handle…
The auto column conversion should be limited to simple and intuitive use cases. It shouldn't trigger the slow ORM recomputation if the field is computed. We always expect an upgrade script to handle more complex use cases.
This commit introduces two changes:
### 1. Removal of `drop_not_null` during auto column conversion
Before https://github.com/odoo/odoo/commit/50767ef90eadeca2ed05b9400238af8bdbe77fb3 We dropped the not_null constraint because the original column would be renamed. After that commit, we actually don't need to drop the not_null constraint since the `convert_column` will neither convert a not-null value to `null` nor convert 'null' to a not-null value. Keeping the not_null constraint shouldn't block the column convert.
### 2. Removal of `column.clear()`
When a computed/related Float field is changed from `digits=None` to `digits='xxx'`, the `column.clear()` will trigger ORM recomputation during upgrade which is useless since `double precision` to `numeric` is lossless. The recomputation in ORM is slow and should be avoided. If the rerounding is really needed, a sql script is required for upgrade or installation.
The `column.clear()` was originally introduced to avoid `Missing not-null constraint` warnings in specific scenarios:
Case 1 (Upgrade Warning): from saas-18.4 to 19.0
old database: Selection field `l10n_be.export.sdworx.leaves.wizard.reference_year` upgrade: pre-migrate `util.rename_model(cr, "l10n_be.export.sdworx.leaves.wizard", "l10n.be.hr.payroll.export.sdworx")` new database: Integer field `l10n.be.hr.payroll.export.sdworx.reference_year` The column value which was a required stringified integer is auto-converted to an integer.
Case 2 (Installation Warning):
In pos_urban_piper, the required field `pos.config.name` is overridden from `translate=False` to `translate=True`. The column value which was a required text is auto-converted to `'{"en_US": "text"}'::jsonb`
The not_null constraint was previously lost by the `sql.drop_not_null` in `update_db_column` and is not restored by `update_db_notnull` because of the inconsistency between the variable `column['is_nullable']` and the actual not_null constraint in the database.
Thanks to change 1, we will no longer lose the not_null constraint in `update_db_column`. The constraint can be kept even without `column.clear()`.
By removing the `column.clear()`, we also revert the meaning of the `column` variable, which is the column's configuration (dict) before `update_db` if it exists, or `None`
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-prUsers can again mark individual invoices or journal items as “No Follow-Up,” so they won’t trigger reminders or appear in follow-up outputs. This also keeps partner follow-up status accurate, improves handling of items without due dates, and ensures exports and follow-up emails only reflect the billable items that still matter.
Original PR description
During the rework of the follow-up report, we removed the "No Follow-Up" field from journal items, making it impossible to exclude individual journal items from triggering a follow-up. In this commit…
During the rework of the follow-up report, we removed the "No Follow-Up" field from journal items, making it impossible to exclude individual journal items from triggering a follow-up. In this commit we do the following: - Re-introduce a field for that, since it is a common requirement to be able to exclude individual items from the follow-up reports. The field is stored on the journal item, but can also be toggled from the journal entry. In case of multiple installments on the invoice, toggling the field on one installment will toggle it for all installments. - Adapt the Follow-Up Report and Customer Statement variants of the Partner Ledger to add a toggle for the "No Follow-Up" field on each report line, that toggles the field on the corresponding journal item(s). - Prevent the follow-up status on the partner to change when all of the overdue journal items are marked as "No Follow-Up". - Make sure users can toggle the "No Follow-Up" setting on the invoice level when opening the "Overdue Invoices" view from the partner's "Accounting" tab. - Make sure all receivable/payable lines without a due date (either from a manual miscellaneous entry or a PoS entry) are put under the "Due" section in the Follow-Up Report instead of the "Overdue" section. Since there is no due date, they can't be overdue. - Make sure the PDF and XLSX exports of the Follow-Up Report don't include the "No Follow-Up" lines, and the customer follow up email only includes the amount of the other lines. Backport of https://github.com/odoo/enterprise/commit/74b9d2ef17e4f9a217db8432d886de2eca4baef9 and https://github.com/odoo/odoo/commit/2789a0fbfa358c5c164e44380c2a4a10e5679615 Task: 5138378 Upgrade PR → https://github.com/odoo/upgrade/pull/8864 Forward-Port-Of: odoo/enterprise#96627
Resolved issues and error corrections
The calendar day view no longer cuts off event titles on mobile devices. This makes it easier for users to quickly understand what each event is without opening it, improving readability and daily planning.
Original PR description
Before this commit, when the user goes to a calendar view in day to check what he have to do. He cannot see the event title properly in his mobile phone since the title is truncated. This commit makes sure the event title is not truncated to clearly see the whole event title. Before the fix: <img width="1172" height="802" alt="image" src="https://github.com/user-attachments/assets/f85a4a03-89a3-48c8-bda7-38e72854ce1f" /> After the fix: <img width="1179" height="808" alt="image" src="https://github.com/user-attachments/assets/7b0b31ba-10f5-412b-837b-8399c78c5bac" /> Forward-Port-Of: odoo/odoo#235823
Fixed an issue where the Timesheets stat button could show dramatically inflated values when timesheets were displayed in days or half-days. This ensures the totals now match the actual time entered, so managers see accurate information in Helpdesk team settings.
Original PR description
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4.…
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4. Open the team’s settings and observe the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the team’s settings and observe the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------ After commit d23ca81, the UoM model was restructured, changing how conversions between hours and days are computed. The field `factor_inv`, previously used in the computation of total_timesheet_time, was removed. Earlier, `factor_inv` handled this conversion correctly. After its removal, the computation now directly uses factor, which leads to incorrect values when converting to days. https://github.com/odoo/enterprise/blob/92bb923ffe185b7744adeadcc8f2972f9a64effb/helpdesk_timesheet/models/helpdesk_team.py#L32-L36 For ex: Consider unit_amount = 20 minutes: **Before** Case 1: Encoding method = Hours/Minutes (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 1 = 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 8 = 160 Days --> INCORRECT **After** Encoding method = Days/Half-days (unit_amount_sum * (1.0 if helpdesk_ticket.encode_uom_in_days else product_uom_factor)) / uom_team.factor (20 * 1) / 8 = 2.5 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. **NOTE:** Before this change, when the user opened the timesheet sublist view in debug mode and clicked the View button, it opened the default form view of the `account.analytic.line` model instead of the intended timesheet form view. This allowed editing of the Unit of Measure (product_uom_id) field also. To prevent this, the form view reference has been explicitly specified, similar to the one used in the [Project module](https://github.com/odoo/odoo/blob/3f23bd9723d9065f17c1960d185d67a0a809a889/addons/hr_timesheet/views/project_task_views.xml#L41). Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related community PR: https://github.com/odoo/odoo/pull/233803 Forward-Port-Of: odoo/enterprise#98545
The Profit and Loss report now correctly includes the new “Other Expenses” account type. This ensures these costs are shown in financial reports instead of being left out, giving a more accurate view of company expenses.
Original PR description
In saas-18.3 a new account type was added: "Other Expenses" These accounts are excluded from the account many2one field to make it easier to find relevant expense accounts for vendor bills. Issue: This account type is not included in the Profit & Loss Report. Since l10n_be is the only CoA which uses this account type, the issue was not uncovered until OXP testing days.
This change prevents an error from appearing in Documents when a related CRM record has already been deleted. Orphaned upload documents are now handled safely, so users can open the Documents app without seeing a traceback.
Original PR description
Steps to reproduce: - Install crm and documents - Go to CRM → Activity Types - Set a folder in the Upload Document activity - Create a CRM lead and schedule an upload document activity - Delete the created lead - Open the Documents module Issue: - A traceback occurs because web_read tries to access values_by_id[record.id], as the upload request document remains in the database after its related activity is deleted. Solution: - fix the recompute of res_name and set it to False, avoiding MissingError opw-5080182 Forward-Port-Of: odoo/enterprise#97461
Project dashboard timesheet totals now display the correct amount when the timesheet setup uses days or half-days. This fixes a conversion error that could show much larger values than expected, helping users trust the figures they see at a glance.
Original PR description
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard…
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard and check the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the project dashboard and check the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------- After this 28b69da, UoM model got restructured and the conversion logic between hours and days changed. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L137-L143 The `total_timesheet_time` value is now already stored in the final unit (e.g., days). The subsequent division in `_get_stat_buttons()` was a redundant **double conversion**, resulting in incorrect display. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L231-L234 **Before** Case 1: Encoding method = Hours/Minutes Consider allocated_hours = 80 Hours, total_timesheet_time = 20 Hours Then: uom_ratio = 1/1 => 1 allocated = 80/1 => 80 Hours effective = 20/1 => 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days Consider allocated_hours = 80 Hours, total_timesheet_time = 2 Days (already in days — no conversion needed, but the system incorrectly tries to convert it) Then: uom_ratio = 1/8 => 0.125 allocated = 80/.125 => 640 Days effective = 2/0.125 => 16 Days --> INCORRECT **After** Consider allocated_hours = 80 Hours (needs conversion to days as per encoding method) and total_timesheet_time = 2 Days (already in days, no conversion). Then: uom_ratio = 1/8 => 0.125 allocated = 80*.125 => 10 Days effective = 2 => 2 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related enterprise PR: https://github.com/odoo/enterprise/pull/98545 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233803
This fix prevents an error that could appear when reopening a page after adding or replacing a Vimeo video in the website editor. It ensures the editor can correctly handle the video item being passed between components, so users can edit and save pages without interruption.
Original PR description
Steps to reproduce: =================== 1- Website app > Open any page in Edit mode. 2- Drag a Video block into the page. 3- Paste a Vimeo video URL in the dialog and save. 4- Save the page, then…
Steps to reproduce:
===================
1- Website app > Open any page in Edit mode.
2- Drag a Video block into the page.
3- Paste a Vimeo video URL in the dialog and save.
4- Save the page, then re-open it in Edit mode.
-> traceback
Cause:
======
The Wysiwyg "openMediaDialog" passes the selected media DOM node as "media" to the MediaDialog.
The MediaDialog forwards that value as "media" prop to VideoSelector. VideoSelector declared "media" as "{ type: Object, optional: true }". Owl validates "type: Object" as a plain object, not as any "typeof object".
DOM elements such as HTMLImageElement do not pass this plain object check, so Owl raises an error.
Solution:
=========
Relax the "media" prop type in VideoSelector so DOM nodes are accepted. In web_editor VideoSelector, change the "media" prop to "{ optional: true }".
In html_editor VideoSelector, also keep "media" declared as "{ optional: true }".
opw-5239889
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#236296This change updates the LinkedIn API version used by the social sharing integration. It was needed because the previous version was retired, helping ensure continued posting and account connection functionality for users.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
This fix ensures the POS uses the right component lines when calculating costs for products with variants in a Bill of Materials. As a result, orders for different variants now show the correct line costs, improving accuracy in reporting and inventory valuation.
Original PR description
When you create a product with atleast one variant that has 2 value, and create a BoM for this product that has 2 lines with each line having one of the two values, then create a POS order with one…
When you create a product with atleast one variant that has 2 value, and create a BoM for this product that has 2 lines with each line having one of the two values, then create a POS order with one unit of each variant, the cost of the first line not correctly computed. Steps to reproduce: ------------------- * Create a prodcut P with one attribute A that has two values A1 and A2 * Create a product C with no attribute and a cost of 10$ * Create a BoM for P with two lines: - Line 1: product C, quantity 1, only for attribute value A1 - Line 2: product C, quantity 2, only for attribute value A2 * Open a PoS session * Add Product P with attribute value A1 to the order * Add Product P with attribute value A2 to the order * Validate the order and close the session * Go to the order and check the cost of each line > Observation: The cost are not correct, they should be 10$ and 20$ Why the fix: ------------ Before this fix we were not taking the `bom_product_template_attribute_value_ids` into account when filtering the stock moves to consider for the cost computation. This value represent the attribute values that the product must have for this BoM line to be considered. opw-4765234 Forward-Port-Of: odoo/odoo#235502 Forward-Port-Of: odoo/odoo#225014
When a manufacturing order’s component quantity was changed, the system could incorrectly mark the component as already picked, which prevented reserving the needed stock again. This fix keeps the component available for reservation when no quantity has actually been consumed, avoiding blocked production orders.
Original PR description
Steps to reproduce the issue:
- Create a storable product “P1” with the following BoM:
- Component: - 1 unit of C1
- Update the quantity on hand of C1 to 10 units
- Create a manufacturing order to produce one unit of P1
- Confirm the order → The quantity of C1 is reserved, and the produced quantity of P1 is 0 (expected behavior)
- Update the component's quantity to consume (C1) to 2
- The consumed quantity is set to 0 and the move marked as picked
- Try to reserve the quantities again
Problem:
Since the move is picked, the
new quantity cannot be reserved.
Solution:
Prevent the move from being marked as picked when the consumed quantity is zero.
opw-5152592This update ensures that when a Point of Sale order linked to a sales order is refunded from the back office, the invoiced quantity is updated correctly on the sales order line. It helps keep sales and invoicing records accurate after refunds.
Original PR description
When doing a refund of a POS order linked to a SO in the backend, the qty_invoiced on the SO line is not updated correctly. Steps to reproduce: ------------------- * Create a SO with 1 quantity of any product * Settle the SO in the PoS * Refund the PoS order from the backend not from the PoS interface * Check the qty_invoiced on the SO line > Observation: The qty_invoiced is still 1 Why the fix: ------------ The method _compute_qty_invoiced was not triggered when the refunding order was paid. So we need to add a new dependency on the function. Note: ----------- In the test we need to flush all before doing the payment of the refund, because if we do not do it, the _compute_qty_invoiced method would be called during the payment. But that is not the case outside of the test. This is just to ensure that the test fails correctly without the fix. opw-4991405 Forward-Port-Of: odoo/odoo#235512 Forward-Port-Of: odoo/odoo#231840
This change prevents an error that could appear when a helpdesk team has no working hours set and a ticket is moved to Done or Canceled. It makes ticket closing more reliable by only applying the working-hours logic when a schedule is actually configured.
Original PR description
> **The issue:** When you go to a helpdesk's team settings -> SLA Policies -> Working hours, set the working hours to empty and then disable SLA Policies and save. After that if you try to move a ticket in the same team to done or canceled you will receive an exception. **Cause:** The part of the code causing the issue is supposed to only run if a Working Hours policy is set. **Fix:** Changed the section of the code to only run when Working Hours is set. opw-5120962 > Forward-Port-Of: odoo/enterprise#98889 Forward-Port-Of: odoo/enterprise#96546
When editing a website, discussion bubbles will now shift aside instead of covering the editor. This makes it easier to select and edit content, especially for users with many active conversations.
Original PR description
Before this commit, discuss bubbles would appear on top of the editor when editing a website. I was therefore be difficult to select some snippets, especially when the user had a lot of conversations at the same time and he wanted to keep the discuss bubbles visible. This commit shift the discuss bubbles on edit to solve the issue. task-4266898 Forward-Port-Of: odoo/odoo#184671
Opening the shop floor from a manufacturing order now takes users to the right work center and keeps the manufacturing order in view. This prevents users from landing on the wrong screen and makes it easier to continue production work without confusion.
Original PR description
Opening shop floor from MO smartbutton activates the WC "Overview". Subsequent opening of shopfloor app will also land on WC "Overview". Also removes an 'undefined' part of local storage key. BEFORE:…
Opening shop floor from MO smartbutton activates the WC "Overview". Subsequent opening of shopfloor app will also land on WC "Overview". Also removes an 'undefined' part of local storage key. BEFORE: Due to an oversight during this fix odoo/enterprise#93553, opening shop floor from MO smartbutton selects the WC from local storage (ie last clicked by user), with a filter for the current MO. (ie. when clicking Shopfloor smartbutton on an MO we can land on the wrong WC) NOW: Opening shop floor from MO smartbutton selects the WC "All MO" with a filter for the current MO. If we close shopfloor and come back to the shop floor app we land back on the "All MO" WC, which is the intended behaviour. Note: I did not rewrite tests I did here: https://github.com/odoo/enterprise/pull/93553/files#diff-2aa7dbd54334d280c72d91b7d472077aaae9af017408f1b0d71150bb16a022f4 as the setup is quite different in 18.0 (no access to the required stepUtils and the tour flow is quite different) task#4629641 Forward-Port-Of: odoo/enterprise#99855 Forward-Port-Of: odoo/enterprise#93841
This update prevents a crash when opening older point-of-sale refund orders created before a data model change. It ensures existing refund records are handled safely after upgrades, avoiding errors during normal use and upgrade checks.
Original PR description
In saas~17.1, the field `refunded_order_id` was changed from a Many2Many to a Many2One, as refunding lines from different orders with the same order was no longer possible. The problem is that there were no changes applied to the existing data to account for this, so databases with those kind of refunds will trigger an error when the field is computed: ``` ValueError: Wrong value for pos.order.refunded_order_id ``` This behaviour can also break upgrades if the error happens during the mock crawl test after the upgrade. To reproduce: - In 17, create an order refunding products from different orders. - Upgrade to 18. - Try to view the refunding order. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224515 Forward-Port-Of: odoo/odoo#221355
4 changes
Resolved issues and error corrections
This update corrects a test used for localized Point of Sale setups so automated checks run reliably again. It helps prevent false failures in the validation process without changing day-to-day store operations.
Original PR description
Fix runbot issue runbot-233183 Forward-Port-Of: odoo/enterprise#99370
The LinkedIn integration header was updated to use a supported API version. This was necessary because the previous version had been retired, helping prevent disruptions when publishing content to LinkedIn.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
This change prevents an error that could happen when closing a helpdesk ticket if the team had no working hours configured in its SLA settings. It ensures the closing process only uses the working-hours logic when that setting is actually present, avoiding interruptions for users.
Original PR description
> **The issue:** When you go to a helpdesk's team settings -> SLA Policies -> Working hours, set the working hours to empty and then disable SLA Policies and save. After that if you try to move a ticket in the same team to done or canceled you will receive an exception. **Cause:** The part of the code causing the issue is supposed to only run if a Working Hours policy is set. **Fix:** Changed the section of the code to only run when Working Hours is set. opw-5120962 > Forward-Port-Of: odoo/enterprise#98889 Forward-Port-Of: odoo/enterprise#96546
This change stops the system from creating or updating a purchase request twice when the same approval is opened in multiple tabs or by multiple users. It helps avoid accidental duplicate quantities on purchase requests and keeps purchasing data accurate.
Original PR description
**Problem:** It's possible to click the "Create RFQ's" button more than once, as the user may have multiple tabs open or multiple users are viewing the same record. When this happens, the approval will create or add to an RFQ even if it already did, and this causes double the intended product quantities. **Solution:** The "Create RFQ's" button becomes hidden when purchase_order_count > 0 (i.e. there are linked POs) so we can perform this check within the button's method `action_create_purchase_orders` to prevent RFQ generation (or modification). opw-5227493 Forward-Port-Of: odoo/enterprise#99706
32 changes
Enhancements to existing features
When half-day or hourly time off was moved to the next month, it could be treated as a full-day absence by mistake. This update keeps the deferred work entry aligned with the actual leave duration, improving payroll accuracy.
Original PR description
When deferring half-day or hourly leaves to the next month, the work entry was incorrectly replaced with a full day duration instead of the actual leave duration. Now splits the work entry to match the exact leave hours when necessary. task-5258753
The transcript download button is now available from the live chat info panel during an active conversation. This makes it easier for internal users to access and save chat records without waiting until the session ends.
Original PR description
Previously, the 'Download Transcript' button was only visible to visitors at the end of a live chat session. This limitation caused confusion since internal users could not download the conversation transcript from the interface. This PR adds the 'download transcript' button to the info panel, ensuring it is accessible from within the chat session as well. Task-5262296 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The stock return wizard now shows one main action button, with the other options styled as secondary actions. The cancel action is also relabeled to "Discard," and users get clearer feedback when trying to return items with zero quantity, making the flow easier to understand and use.
Original PR description
Previously, the return wizard displayed multiple primary buttons, which could confuse users and affect the clarity of actions. This commit updates the wizard to have a single primary button, with all other action buttons changed to secondary for better user experience. Additionally, some button labels have been updated for clarity: - `Cancel` → `Discard` These changes make the return wizard more consistent, intuitive, and easier to use for all types of stock operations. This commit also enables improved user error when attempting to return products with zero quantities. Task - 5144914
This change makes large financial reports compute much faster by reusing already calculated account balances instead of recalculating the same data many times. It reduces waiting time for users running reports, especially on big databases, while keeping the result unchanged.
Original PR description
### Issue Large financial reports are slow to compute due to repeated re-aggregation of account_move_line balances for each formula, even when most formulas share the same base domain (usually…
### Issue
Large financial reports are slow to compute due to repeated re-aggregation of account_move_line balances for each formula, even when most formulas share the same base domain (usually filtered by account_id fields).
### Analysis
Each report line formula independently aggregates balances from account_move_line, even when their domains only differ on account_id-related fields such as account_id.account_type or account_id.non_trade.
This leads to redundant scanning and aggregation of the same dataset multiple times within a single report execution.
### Solution
Introduce a lightweight in-memory caching layer for aggregated balances by account_id, stored in self.env.cr.cache.
For each (options, date_scope) pair:
The report engine now computes once the mapping
{account_id: {'amt': total_balance, 'count_aml_lines': count}}.
This mapping is stored in the cursor cache and reused across all formulas whose domains filter exclusively on account_id fields.
A small domain transformation step allows AML domains based on account_id.* fields to be evaluated directly against the cached account aggregates.
This approach avoids redundant SQL aggregation, remains fully read-only (no database writes), and is safe for execution on read replicas.
### Benchmarks
Profiling get_report_information_readonly on different reports. Database has ~11.6 million account_move_lines, 305 account_accounts, and 16 account_types
| Report Name | Before | After | % Speed Up |
| --- |---|---|---|
| Balance Sheet | 35s | 6.2s | ~550% |
| Profit and Loss | 7.2 | 2.1 | ~300% |
| Cash Flow Statement | 1.5s | 0.4s | ~300% |
| Executive Summary | 24s | 6.3 | ~400% |
### References
opw-5130725Resolved issues and error corrections
This update prevents a crash that could happen when users open agent report charts grouped by help status in live chat. It makes help-related chat sessions load normally again, improving reliability for support teams reviewing chat activity.
Original PR description
The `help_status` field of the channel member history model is used to quickly find sessions where help was requested/provided. However, the field exposes a `_search` method that doesn't exists which lead in a crash when clicking on the agent report bars when grouping by `help_status`. This field is stored so we don't need the search. Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236648
This update keeps the external tax sales feature aligned with recent changes in the core Odoo community code. It helps prevent test or behavior mismatches so the sales experience remains reliable.
Original PR description
See Also: - https://github.com/odoo/odoo/pull/227241
The sign sending wizard now avoids checking another user’s signature or initials unless it is actually needed. This prevents a permissions error when preparing documents with multiple roles and multiple internal users, making the signing flow open reliably.
Original PR description
Before this commit, The following traceback was encountered when the sign.send.request wizard was opened in the following conditions: - sign.template with signature/initials fields and more than one…
Before this commit, The following traceback was encountered when the sign.send.request wizard was opened in the following conditions:
- sign.template with signature/initials fields and more than one role
- more than one sign user (internal user)
```
File "/home/user/workspace/odoo/src/19.0/enterprise/sign/wizard/sign_send_request.py", line 341, in _compute_only_autofill_readonly
not (item.type_id.name == 'Signature' and request._get_user_signature(user, 'sign_signature')) and
~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/workspace/odoo/src/19.0/enterprise/sign/wizard/sign_send_request.py", line 323, in _get_user_signature
return user[signature_type]
~~~~^^^^^^^^^^^^^^^^
File "/home/user/workspace/odoo/src/19.0/odoo/odoo/orm/models.py", line 6680, in __getitem__
return self._fields[key].__get__(self)
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/home/user/workspace/odoo/src/19.0/odoo/odoo/orm/fields.py", line 1646, in __get__
record._check_field_access(self, 'read')
~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/home/user/workspace/odoo/src/19.0/odoo/odoo/orm/models.py", line 3426, in _check_field_access
raise AccessError(error_msg)
odoo.exceptions.AccessError: You do not have enough rights to access the field "sign_signature" on User (res.users). Please contact your system administrator.
```
This commit ensure that we don't try to access the signature/initial field of another user when it is not necessary.
task-5271648This fix corrects the timesheet total displayed on Helpdesk team pages when timesheets are configured in days or half-days. It prevents values from being overstated, so users now see an accurate summary of logged time.
Original PR description
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4.…
Steps to reproduce: -------------------- 1. Install helpdesk_timesheet 2. Create a new team with timesheets enabled 3. Create a new ticket and add a timesheet line with some time (e.g., 20 hours) 4. Open the team’s settings and observe the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the team’s settings and observe the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------ After commit d23ca81, the UoM model was restructured, changing how conversions between hours and days are computed. The field `factor_inv`, previously used in the computation of total_timesheet_time, was removed. Earlier, `factor_inv` handled this conversion correctly. After its removal, the computation now directly uses factor, which leads to incorrect values when converting to days. https://github.com/odoo/enterprise/blob/92bb923ffe185b7744adeadcc8f2972f9a64effb/helpdesk_timesheet/models/helpdesk_team.py#L32-L36 For ex: Consider unit_amount = 20 minutes: **Before** Case 1: Encoding method = Hours/Minutes (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 1 = 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days (unit_amount_sum / product_uom.factor) * uom_team.factor (20 / 1) * 8 = 160 Days --> INCORRECT **After** Encoding method = Days/Half-days (unit_amount_sum * (1.0 if helpdesk_ticket.encode_uom_in_days else product_uom_factor)) / uom_team.factor (20 * 1) / 8 = 2.5 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. **NOTE:** Before this change, when the user opened the timesheet sublist view in debug mode and clicked the View button, it opened the default form view of the `account.analytic.line` model instead of the intended timesheet form view. This allowed editing of the Unit of Measure (product_uom_id) field also. To prevent this, the form view reference has been explicitly specified, similar to the one used in the [Project module](https://github.com/odoo/odoo/blob/3f23bd9723d9065f17c1960d185d67a0a809a889/addons/hr_timesheet/views/project_task_views.xml#L41). Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related community PR: https://github.com/odoo/odoo/pull/233803 Forward-Port-Of: odoo/enterprise#98545
The LinkedIn integration was updated to use a newer API header version after the previous one was sunset. This helps keep social account publishing connected and working with LinkedIn’s current API requirements.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
The project dashboard now shows the correct timesheet totals when time is entered in days or half-days. This fixes a display error that could make the stat button show much larger values than expected, helping teams trust the figures they see at a glance.
Original PR description
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard…
Steps to reproduce: -------------------- 1. Install hr_timesheet 2. Create a new project and a task 3. On the task, add a timesheet line with some time (e.g., 20 hours) 4. Open the project dashboard and check the Timesheets stat button 5. Go to Timesheets > Configuration > Settings 6. Set "Encoding method" to "Days/Half-days" 7. Reopen the project dashboard and check the Timesheets stat button again Issue: ------ Incorrect value displayed in the Timesheets stat button. (e.g., 160 Days instead of 2.5 Days) Cause: ------- After this 28b69da, UoM model got restructured and the conversion logic between hours and days changed. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L137-L143 The `total_timesheet_time` value is now already stored in the final unit (e.g., days). The subsequent division in `_get_stat_buttons()` was a redundant **double conversion**, resulting in incorrect display. https://github.com/odoo/odoo/blob/aeda822db05b218fd1271c7666307950b7a98512/addons/hr_timesheet/models/project_project.py#L231-L234 **Before** Case 1: Encoding method = Hours/Minutes Consider allocated_hours = 80 Hours, total_timesheet_time = 20 Hours Then: uom_ratio = 1/1 => 1 allocated = 80/1 => 80 Hours effective = 20/1 => 20 Hours --> CORRECT Case 2: Encoding method = Days/Half-days Consider allocated_hours = 80 Hours, total_timesheet_time = 2 Days (already in days — no conversion needed, but the system incorrectly tries to convert it) Then: uom_ratio = 1/8 => 0.125 allocated = 80/.125 => 640 Days effective = 2/0.125 => 16 Days --> INCORRECT **After** Consider allocated_hours = 80 Hours (needs conversion to days as per encoding method) and total_timesheet_time = 2 Days (already in days, no conversion). Then: uom_ratio = 1/8 => 0.125 allocated = 80*.125 => 10 Days effective = 2 => 2 Days --> CORRECT Reference: The [UoM’s factor ](https://github.com/odoo/odoo/blob/ca9df34f3a29796596f92e55647f61f95a95af52/addons/uom/data/uom_data.xml#L29-L37)has also been changed. Solution: ---------- This commit ensures accurate conversion of timesheet values between hours and days opw-5184077 Related enterprise PR: https://github.com/odoo/enterprise/pull/98545 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#233803
The “View Quotation” button in purchase order emails now sends recipients to the correct company website instead of the default site. This prevents confusion for users working across multiple websites or companies and ensures customers land on the expected page.
Original PR description
Versions -------- - 17.0+ Steps ----- 1. Host a server with demo data on localhost; 2. create & switch to a second company; 3. have a website linked to the second company; 4. set the website's domain to http://2.localhost:8069; 5. create a purchase order; 6. send order via email; 8. open mail via Settings / Technical / Email / Emails. Issue ----- The "View Quotation" button links to the default URL instead of the second company's website. Cause ----- The button added via `_notify_get_recipients_groups` only adds a relative URL, which then defaults to the database's base url when sent. Solution -------- Use an absolute URL, using the order's `get_base_url` method. opw-5035391 Forward-Port-Of: odoo/odoo#236598 Forward-Port-Of: odoo/odoo#233255
This update makes section and optional-line handling more consistent in sales and accounting screens. It fixes visibility rules, move/reorder behavior, and default quantities so users see fewer confusing actions and get more predictable totals and section states.
Original PR description
This PR consolidates multiple fixes and improvements across **account**, **sale_management**, and **sale** to make the section widget more internally consistent. It addresses visibility rules,…
This PR consolidates multiple fixes and improvements across **account**, **sale_management**, and **sale** to make the section widget more internally consistent.
It addresses visibility rules, optional section logic, resequencing behavior, and some configurator quirks.
---
### **1. Section Widget: Hide Prices / Hide Composition Logic**
* Subsections under a hidden section now correctly disable both *Hide Prices* and *Hide Composition*.
* Subsections under a *Hide Prices* section cannot hide prices, but may still hide composition.
* Mutually exclusive states: a section cannot have *Hide Prices* and *Hide Composition* active at the same time.
* Resequencing a subsection under a *Hide Composition* section resets all its state flags.
* Removed confusing buttons:
* “Add a Section” inside a section
* “Add a Subsection” inside a subsection
---
### **2. Optional Section Behavior (sale_management)**
* Optional sections and subsections cannot activate *Hide Prices* or *Hide Composition*.
* Subsections under a *Hide Prices* section cannot hide prices or become optional (but can hide composition).
* Resequencing into a section with *Hide Composition* resets all child states to `false`.
* New lines inside optional sections default to quantity **0**.
* Setting a section as optional resets all nested `collapse_*` states.
---
### **3. Resequencing Logic for Optional Sections**
Improved behavior when moving sections and lines:
* **Quantity rules**
* Moving a line **into** an optional section → qty → `0`
* Moving a line **out** of an optional section → qty → `1`
* Same logic applies when moving entire sections that change which lines fall under them.
* **Recalculation rules**
* Moving a section **up**:
* Recompute all lines under the moved section.
* Recompute all lines between old/new positions.
* Moving a section **down**:
* Recompute all lines under crossed sections.
* Recompute all lines between old/new positions (excluding overlaps).
---
### **4. Combo Line Move Fix (sale)**
* Unsaved combo lines were missing *Move Up/Down* due to `virtual_id` not being considered.
* Updated logic to include `linked_virtual_id` so combos can be moved even when unsaved.
---
### **5. Other Fixes**
* Made dynamic conditional labels translatable (Hide/Show Prices, Hide/Show Composition, Set/Unset Optional).
* Updated the relevant XPath introduced in earlier commits.
* Removed an archived product from quotation template demo data.
* Added mobile UI controls for section toggles (`collapse_prices`, `collapse_composition`, `optional`).
* Configurator adjustments for optional-section products:
* Hide quantity controls, price, and total.
* Added products default to qty `0` inside optional sections.
See Also:
- https://github.com/odoo/enterprise/pull/99188
task-5082193This update adds automated coverage for mention suggestions inside channels that are limited to specific groups. It helps ensure users continue to see the correct mention behavior in these restricted discussions after future changes.
Original PR description
This commit adds a test for mention suggestions in group-restricted channels (`group_public_id`). task-5258925 Forward-Port-Of: odoo/odoo#235478
This update fixes two issues on the recruitment website: visitors who are not logged in will now be redirected to the correct local job page, and job counts will display correctly even when users cannot access all underlying records. It also corrects a counting error that could show the wrong number of open jobs when results were grouped in a different way.
Original PR description
This commit fixes 2 bugs: When you are not logged in and geolocalized, we don't redirect the visitor to the right country because the visitor cannot read hr.job, so the count will always be 0. Now we use sudo to have the count whether you are logged in or not. Another bug is in compute_filter_selection_counters: in case you provide a key_getter that is not the same as the grouping_field, when we count, we only keep the last count in case of duplicates. Eg, if you group by address_id and count the address_id.country_id, you will get the count of hr.job open in the last office you iterate over. Forward-Port-Of: odoo/odoo#234713
The Italian monthly VAT report now calculates the VP6 due/deductible line correctly. This fixes cases where the report could show an inflated total, helping ensure more accurate VAT reporting.
Original PR description
The VP6 - VAT due/deductible line of the Italian Monthly VAT Report, introduced in https://github.com/odoo/odoo/commit/51a72ab42d118d6fb0eb3e3545a09e10019b9140, was using an incorrect `formula`. For instance, €200 due and €100 deductible resulted in €300 instead of the expected €100. This commit fixes the computation. Ticket [link](https://www.odoo.com/odoo/project.task/5178831) opw-5178831 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The helpdesk ticket view was updated so the status badge uses the new widget setup correctly. This keeps the interface working smoothly after an internal performance-related change and helps avoid display issues for users.
Original PR description
This commit adapts the definition of the field using the `badge_rotting` widget since that widget no longer extend to SelectionBadge widget due to a perfomance issue.
This update changes how stage/status badges are shown in list views so they no longer trigger extra background requests for each project. The result is smoother performance when users review and update many records at once, especially in task, lead, and applicant lists.
Original PR description
Before this commit, the rotting feature uses the selection_badge widget to be rendered in the list view. The problem is the selection_badge will do one rpc per project for the tasks displayed in the list view of all tasks to have all available stages when the user wants to update the stage. This commit changes the widget used to use a custom many2one field widget for rotting in list view to make sure no extra rpc is made.
When processing kit components in the barcode app, scanning an available serial/lot now updates the originally reserved line instead of creating a separate one. This prevents unnecessary backorder prompts and makes delivery validation behave as users expect.
Original PR description
### Issue: Scanning an unreserved lot of a kit component creates a new barcode line rather than updating the value of the initially reserved lot. As a result, the backorder porcess considers that…
### Issue:
Scanning an unreserved lot of a kit component creates a new barcode line rather than updating the value of the initially reserved lot. As a result, the backorder porcess considers that every unscanned yet initially reserved quantity is to backorder.
### Steps to reproduce:
- Create a kit product with a kit BOM:
- 1 x COMP (tracked by SN)
- Add two Serial numbers SN001 and SN002 in stock for the COMP product
- Create and confirm a delivery order for 1 unit of oyur kit product
- Go the barcode app to process your delivery
- Scan SN002
> A new line is created instead of updating the initial reservation
- Validate the delivery
#### > A backorder dialog opens proposing to update the unscanned reservation
### Cause of the issue:
Scanning a lot will first try to find a line to update, however, currently a line will only be found if the scanned lot has been reserved or if no particular lot has been reserved:
https://github.com/odoo/enterprise/blob/a1113eebf634302f7ceece612e7ee068c99781e4/stock_barcode/static/src/models/barcode_model.js#L1659-L1661 https://github.com/odoo/enterprise/blob/a1113eebf634302f7ceece612e7ee068c99781e4/stock_barcode/static/src/models/barcode_model.js#L743-L746 In particular, since no line is considered as valid, a new line is created. And, since this new line does not refer to any `move_id` while the existing one does, the move with the initial reservation will be backordered considering none of its demand was fulfilled: https://github.com/odoo/enterprise/blob/a1113eebf634302f7ceece612e7ee068c99781e4/stock_barcode/static/src/models/barcode_picking_model.js#L904-L921
### Fix:
In order to loosen the condition of lot override on barcode lines we add a check on the package and the location of the line in order to avoid use cases where the initial move line already contains info's that are proper to the initial lot.
opw-5100026
Forward-Port-Of: odoo/enterprise#99845
Forward-Port-Of: odoo/enterprise#98589Mail information is now fetched using the correct company access rules, so users only receive the data they should see. The broader access was kept only for avatar cards, where it is needed, which helps avoid loading extra information by mistake.
Original PR description
Before this commit, all mail data were retrieved with a context containing all companies ids, which therefore was fetching more data than expected. This behaviour was the desired one only for the `avatar_card`. With this commit, we revert the context to what was existing previously and only apply the all companies context to the avatar card. task-5322823 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
We fixed an issue that added unwanted blank space around horizontal lines in mass mailings. This makes email layouts look cleaner and prevents spacing problems when using certain content snippets.
Original PR description
This [commit] introduced an issue in `mass_mailing` where `[data-selection-placeholder]` paragraph take up vertical space when they were not designed to. How to reproduce: - create a new mass_mailing - add the snippet "pricelist" Issue: - Horizontal lines have extra blank space around them (empty `[data-selection-placeholder]` paragraphs Resolution: - Use the related style asset for these nodes from html_editor, and add `!important` on the margin-bottom style property value, to ensure that the Design Tab does not override it. - Since `mass_mailing` does not use `web.assets_frontend` anymore, files from new features in the `html_editor` may not automatically be included in `mass_mailing` bundles. A future task will refactor assets bundles so that this problem does not occur again. [commit]: https://github.com/odoo/odoo/commit/edf7f7bb0c62978640c181eccb4934855d5d872d task-5265692
This update makes the Belgian POS black box communication more resilient by retrying when the device returns an invalid response or a NACK. It also enforces the documented 1.5-second maximum timeout, helping reduce failed transactions caused by temporary device communication issues.
Original PR description
Following documentation, max timeout should be 1.5s and we should retry 3 times on every bb NACK/invalid data. Forward-Port-Of: odoo/enterprise#99911 Forward-Port-Of: odoo/enterprise#99705
This fix prevents an error that could appear when a helpdesk ticket is moved to Done or Canceled after SLA working hours were cleared. It ensures the system only checks working hours when that setting is actually enabled, avoiding interruptions for support teams.
Original PR description
> **The issue:** When you go to a helpdesk's team settings -> SLA Policies -> Working hours, set the working hours to empty and then disable SLA Policies and save. After that if you try to move a ticket in the same team to done or canceled you will receive an exception. **Cause:** The part of the code causing the issue is supposed to only run if a Working Hours policy is set. **Fix:** Changed the section of the code to only run when Working Hours is set. opw-5120962 > Forward-Port-Of: odoo/enterprise#98889 Forward-Port-Of: odoo/enterprise#96546
This change prevents a crash that could happen when reopening a Point of Sale register with the default preset set to Takeout. It ensures the register only creates a new order at the right stage, so users can reopen the register normally without seeing a traceback.
Original PR description
STEPS TO REPRODUCE: -------- 1. Set default preset as Takeout in configuration. 2. Open a register than Close the register. 3. Reopen the register. 4. Observe traceback. CAUSE: ----------------- LoginScreen created an order before the ProductScreen was loaded causing preset logic to access undefined order data. FIX: ----------------------------- Create a new order only when the selected screen is ProductScreen: Task-5237713 Forward-Port-Of: odoo/odoo#234494
This update fixes an issue where card images could show white borders when a hover animation was applied on the website. It improves the visual presentation of image cards so they stay properly filled and look clean when users edit and preview pages.
Original PR description
Step to reproduce: 1. Open website 2. Click edit button and drop s_three_columns snippet 3. Click image and change animation option into hover 4. Some extra white space shown. Before this commit: Applying a hover animation on card images caused the `object-fit` property to unintentionally switch from `cover` to `contain`, resulting in visible white borders around the image.This happened because of the `geo_square` shape, which is automatically injected when a hover effect is applied and no user shape is chosen. This behavior was intentionally introduced in PR [1]. After this commit: Now cropped images use object-fit: contain to preserve the visible properly. and after stretch option apply it can take cover of this container. so his ensures the image fully covers its container without leaving any white gaps. [1]:https://github.com/odoo/odoo/pull/119197 task:4875770 Forward-Port-Of: odoo/odoo#215766
This change corrects missing test information in the VoIP test suite so automated HOOT runs no longer fail on invalid component data. It improves test reliability and helps ensure VoIP checks complete successfully during development and validation.
Original PR description
Before this commit, running VoIP tests in HOOT results in this error: > Global OwlError: Invalid props for component 'TabEntry': 'title' is not a string, 'phoneNumber' is not a string This is because one of the test is setup with incomplete data (no phone number). After this commit, test data is correctly set with a phone number, fixing the props validation error.
This change fixes an issue in the HTML editor where using Select All and Backspace could leave part of a mention behind. It ensures mentions are removed correctly when users clear the entire message, making editing behave as expected.
Original PR description
currently, when selecting all content (ctrl+A) in the html composer and deleting it (Backspace), if there is a mention in the content, only the text part of the selection is deleted, the rest remains. To reproduce: 1. mention a partner in the html composer, type some text after. 2. selecting all content (ctrl+A) and delete it (Backspace). 3. only one character will be deleted, the rest remains. This is the select all selects the deepest text nodes, meaning that the ndoe in the mention link will be selected. However, it is inside a protected node, so will lead to this issue. This commit fixes the issue by overriding the select all behavior when the selection contains protected nodes, to select the whole protected node instead of its content. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects how changes made in the document sharing wizard are saved when allowing link access. As a result, link-sharing settings are now applied properly and users can rely on the updated access options being kept.
Original PR description
This commit fix the 'action_allow_link_access' method in 'documents.sharing' model by adding the 'WRITE_VALUE_PREFIX' to the updated fields. Otherwise the changes wasn't taken into account. Task-5220965
Mentions placed directly in the message editor are now automatically wrapped correctly, which prevents them from becoming stuck or difficult to edit. This improves the reliability of typing and editing messages, especially when working with mentions.
Original PR description
In some cases, mentions can be inserted directly into the editable area without being wrapped in a base container. This can lead to issues when trying to edit or delete the mention, as the mention is a protected node. This commit updates the MentionPlugin to ensure that any mentions found directly under the editable area are wrapped in a base container. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update prevents conditional display rules from reappearing incorrectly after changing the recipient model and using undo/redo in the mass mailing editor. It keeps the snippet state accurate, avoiding invalid rules that no longer match the selected model.
Original PR description
There is an issue with conditionally visible snippets in `mass_mailing` where a user is able to undo in the editor the reset of a filter caused by a recipient model change. How to reproduce: - Create a mass_mailing and add a conditional display rule on a snippet - Change the recipient model - undo, then redo Issue: - The rule appears again on the element, even though the model still has the new value. The domain is invalid, since it applied only on the previous model Resolution: - Make the `data-filter-domain` a `system_attribute` so it is not registered in the editor history. To inform the view that there was a change, `onChange` is called directly when the attribute value changes. task-5263043
This change reverts a recent update that was causing some journal entry lines to be calculated incorrectly when users added new lines. It helps ensure debit and credit amounts are computed reliably again during editing, preventing accounting errors in the interface.
Original PR description
This reverts commit 17d0e67106a30a46d608331680e5094dbc44e2e0. The commit is reverted because the `journal_line_ids` field is causing issues with onchange methods that rely on cached values. Specifically, the automatic computation of `debit`/`credit` when adding new lines to a journal entry was failing. While `journal_line_ids` (as a subset of `line_ids`) works correctly when the data is stored in the database, its absence during an onchange computation (which relies solely on cache) led to incorrect behavior. no-task Forward-Port-Of: odoo/enterprise#99875
This update reverts a change that was causing journal entry lines to behave incorrectly when users added or edited entries. It restores reliable automatic calculation of debit and credit amounts, which helps prevent posting and entry issues in accounting workflows.
Original PR description
This reverts commit 6ed1e43b3f7d53c6a45fe24a1c68f8386e6adf8e. The commit is reverted because the `journal_line_ids` field is causing issues with onchange methods that rely on cached values. Specifically, the automatic computation of `debit`/`credit` when adding new lines to a journal entry was failing. While `journal_line_ids` (as a subset of `line_ids`) works correctly when the data is stored in the database, its absence during an onchange computation (which relies solely on cache) led to incorrect behavior. In stable versions, `journal_line_ids` is: * Kept but deprecated. * Made non-exportable. The field will be removed in `master`. task-5241650 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#236457
This fix prevents Point of Sale refund orders from breaking after an upgrade when they were created with older data patterns. It ensures existing refund records can still be opened and processed normally, reducing upgrade-related errors.
Original PR description
In saas~17.1, the field `refunded_order_id` was changed from a Many2Many to a Many2One, as refunding lines from different orders with the same order was no longer possible. The problem is that there were no changes applied to the existing data to account for this, so databases with those kind of refunds will trigger an error when the field is computed: ``` ValueError: Wrong value for pos.order.refunded_order_id ``` This behaviour can also break upgrades if the error happens during the mock crawl test after the upgrade. To reproduce: - In 17, create an order refunding products from different orders. - Upgrade to 18. - Try to view the refunding order. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#224515 Forward-Port-Of: odoo/odoo#221355
12 changes
Enhancements to existing features
This change makes the system find delivery information for product lots much faster by reworking how the lookup is done behind the scenes. It reduces the number of database reads and removes repeated processing, which can significantly speed up stock operations for larger batches.
Original PR description
### Description: This refactoring replaces the recursive calculation in `_find_delivery_ids_by_lot` with an iterative process. This change significantly reduces the amount of database queries by prefetching and batching all required lines in a single pass, and it also eliminates the overhead caused by repeated recursive function calls. ### Benchmark: | Total Lots | Before | After | |------------|--------|--------| | 69 | 1 sec | 106 ms | | 1152 | 1 min | 5 sec | ### Reference: opw-5096599 Forward-Port-Of: odoo/odoo#233478
The customer portal now reads subscription billing periods from the system configuration instead of relying on a fixed list. This prevents errors when businesses use custom periods such as daily subscriptions, and makes the portal more adaptable to future changes.
Original PR description
Problem -------- In v18.0, the day billing period was removed from the sale.subscription.plan model. For our use case, we require daily subscriptions, so we added this value back to the…
Problem -------- In v18.0, the day billing period was removed from the sale.subscription.plan model. For our use case, we require daily subscriptions, so we added this value back to the billing_period_unit selection field via inheritance. However, this customization causes an error (a KeyError) when accessing the customer portal at /my/subscriptions/<int:order_id>. This is because the controller logic relies on a hardcoded list of periods and does not account for the new custom "day" value. - Screenshot Order with plan Daily: <img width="1246" height="483" alt="image" src="https://github.com/user-attachments/assets/5dc5ca0d-a2f2-434d-8183-15a0424d9f34" /> - Screenshot when trying to get in order on the website: <img width="1250" height="776" alt="image" src="https://github.com/user-attachments/assets/5b10504e-71e2-4c13-8611-39e8a41e05d1" /> Proposed Solution -------- This PR improves the subscription portal by dynamically retrieving billing periods instead of using a hardcoded list. The portal now reads the available options directly from the billing_period_unit field's selection (i.e., self.env['sale.subscription.plan']._fields['billing_period_unit'].selection). This improves maintainability, as future changes to the field's selection will be automatically reflected without requiring code modifications. This makes the portal robust and automatically compatible with any custom periods added via inheritance. - <img width="1331" height="752" alt="image" src="https://github.com/user-attachments/assets/4f7be6c3-d96b-4525-8e23-6e1323adabde" />
The tax closing process now warns users if they try to close a later period while an earlier one is still open. This helps prevent gaps that could break carryover calculations, especially for reports that depend on a continuous closing order.
Original PR description
For instance with a monthly periodicity and the last closed period is January: When we try to close March, it will show a warning telling us a period in between is not yet closed. This only applies to report with carryover as it can break the carryover chain if we don't do it in the order task-4252735
This update makes the fields used in Sign templates easier to customize and extend. It helps developers adapt template behavior more cleanly in future patches without changing core logic directly.
Original PR description
Introduced a dedicated _getTemplateFields() method to make easier to override or extend the fields in patches.
Resolved issues and error corrections
This fixes a calculation issue when importing Italian EDI vendor bills or credit notes that contain a Maggiorazione discount. The line total now keeps the correct sign and amount, preventing incorrect totals on imported documents.
Original PR description
Since commit #206238, discounts of type "MG" (Maggiorazione) caused the line total amount sign to flip, leading to incorrect calculations of the total amount. **Steps to reproduce:** - Import a vendor bill/credit note XML (Italian EDI). - Include a line with a Maggiorazione discount. - The line total amount currently appears with the wrong sign and/or amount. Ticket [link](https://www.odoo.com/odoo/project.task/5220218) opw-5220218
This change updates the version information used for LinkedIn connections so the integration continues to work with the current API. It was needed because the previous version has been retired by LinkedIn, which could otherwise disrupt social posting and account syncing.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
When users create a contact from suggested recipients in the full message composer, Odoo now correctly keeps the suggested name and email details. This prevents missing or incorrect partner information, especially in CRM, where lead data could previously be transferred incorrectly.
Original PR description
When a partner is created from suggested recipients for the composer, values suggested for its creation are not used. Whereas they should be used, just like is the case when sending a message from the small composer. We just need to normalize the emails from the "additional values" dict on the server. As was done in [1] for the post route (small composer). Additionally the suggested recipient for leads is updated to use the contact name if available, to match suggested recipient values which defaults to assuming we are creating an individual (not a company) task-5241064 [1]: https://github.com/odoo/odoo/commit/67c5a61b09e199430a48aa15a899ac05c761ad6a
When a subscription delivery is returned, the system now properly updates the sold quantity on the order line. This keeps subscription invoicing and delivery figures aligned after returns, preventing incorrect quantities from being reported.
Original PR description
**Steps to reproduce** - Create a new subscription using a subscription product. Confirm it. - Run the "Sale Subscription: generate recurring invoices and payments" scheduled action to generate the delivery. Validate the delivery. - Return the delivery and validate the return. - Issue: the delivered quantity of the sale order line is not updated. **Cause** Currently, we consider a move as related to a subscription period based on the `date_deadline` field (see _get_outgoing_incoming_moves). Since `_prepare_procurement_values` is not called when creating a return, the `date_deadline` is not set on the return moves. **Change** The returns linked to a move in a subcription period will be conisdered for the computation of the delivered quantities. opw-5136406 Forward-Port-Of: odoo/enterprise#98690
This fix stops users from accidentally changing values that should be read-only when they drag and drop items in Gantt planning views. It helps avoid unintended updates to planned work, such as changing the wrong product or work center during scheduling.
Original PR description
Issue ----- Gantt view's drag & drop allows the user to change the value of readonly fields if they are stored. E.G. in the Planning view of MRP, grouped by Work Center > Product, dragging & dropping…
Issue ----- Gantt view's drag & drop allows the user to change the value of readonly fields if they are stored. E.G. in the Planning view of MRP, grouped by Work Center > Product, dragging & dropping can change the product of the WO if the user is not careful and drops the WO on top of another product's WO. Steps to reproduce ----- - Have 2 products - Create a MO for product 1 with a WO at work center 1, plan it - Create a MO for product 2 with a WO at work center 2, plan it - Got to Manufacturing, Planning, Planning by Work Center - Add a custom group (by product) - Drag the WO of WC2 and drop it on top of the other WO > Both the WC and the product of the second WO change Cause ----- The example problem is only for versions 17.0 & 18.0 where the `product_id` field of `mrp.workorder` is both readonly and stored. https://github.com/odoo/odoo/blob/31e46a841b38de0f99beb1844f985bc670621486/addons/mrp/models/mrp_workorder.py#L34 While the user cannot change the field value manually, automatic actions such as a gantt view drag & drop can change its' value by passing it to `write` since the field is stored. This does not pose any problem for related fields that are not stored. More broadly, gantt views should not ignore the `readonly` attribute of fields. Solution ----- Add a new `o_gantt_readonly` class to all cells of rows grouped by a readonly field - and their "child" rows. For example, if the grouping is done by "Work Center > Product > Quality Check" and "Product" is readonly, rows grouped by either "Product" or "Quality Check" will be marked as readonly. When the user drags a pill, dynamically remove the class from cells of the same "child group". The class will then be added back upon pill drop. ----- Ticket: opw-4875366 Forward-Port-Of: odoo/enterprise#94166
The stock forecast now uses the actual received quantity for completed stock moves instead of the originally planned amount. This fixes incorrect future/past forecast numbers when a receipt is validated for less or more than expected, helping users trust the inventory forecast shown on product pages.
Original PR description
### Steps to reproduce: - Create a storable product - Create a receipt for 100 units of that product - Mark as to do, set the quantity to 50 and validate without backorder - Go to your product form >…
### Steps to reproduce: - Create a storable product - Create a receipt for 100 units of that product - Mark as to do, set the quantity to 50 and validate without backorder - Go to your product form > Forecast #### > The forecast displays a quantity of -50 for every date in the past ### Cause of the issue: The part of the report query relying on done moves is based on the `prodcut_uom_qty` of the move and hence on its demand. However, when the move is 'done' only its quantity should be relevant. #### Note: The same issue happen if you receive more than the demand. That is: - Mark as to do, set the quantity to 150 and validate without backorder - Go to your product form > Forecast #### > The forecast displays a quantity of 50 for every date in the past The issue did not happen prior to 17.0 because validating a move for a quantity that differs from the demand would: - in case quantity < product_uom_qty: split the move in 2: one done move where the demand matches the quantity and one cancelled move with the remaining demand. - in case quantity > product_uom_qty: the demand of the move was updated to match the quantity of the move. This has been changed in f9867a5fa572a15fb89c49c61e569427d6388cbc now, validating a move for a quantity that differs from the demand will keep the demand intact. opw-5152570 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change corrects a field calculation issue in the Uruguay electronic invoicing stock flow. It prevents build failures and helps ensure stock-related documents are processed correctly.
Original PR description
runbot build error id: 234034
Documentation and clarification updates
This change updates the Adhoc Contributor License Agreement documentation by adding new members to the approved list. It matters because it keeps the legal records current and ensures contributions can be processed under the correct agreement.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
11 changes
Enhancements to existing features
This update improves how GSTR-2B issues are handled by recognizing an additional error code and treating it as a warning. It also prevents background jobs from reprocessing records that are already in an error state, which reduces unnecessary processing and helps keep return period handling more reliable.
Original PR description
Before this commit: - `RET2B1017` error code was not handled. - Cron methods `_cron_get_gstr2b_data` and `_cron_gstr2b_match_data` processed all records with status: - `"waiting_reception"` - `"being_processed"` - Records with blocking level `"error"` were still being processed by cron. After this commit: - Added handling for `RET2B1017` and mapped it to `"warning"` level. - Updated cron domain filters to exclude records where `gstr2b_blocking_level = "error"`. - Cron jobs now skip invalid/error-state return periods, preventing unnecessary processing.
Resolved issues and error corrections
When a customer used split payment in Point of Sale, payments could be linked to a different contact than the sale itself if the customer was a child contact. This update makes sure the payment and the order use the same accounting partner, keeping customer statements balanced and consistent.
Original PR description
### Description Before this commit, when split payment was enabled for a payment method and a PoS order was assigned to a child contact, the accounting move for the payment was linked to the child contact, while the order move lines were linked to the parent contact. This inconsistency resulted in unbalanced customer statements. This commit ensures that the payment move is assigned to the same accounting partner as the order lines. ### How to reproduce: * Create a child contact (res.partner). * Activate "Identify Customer" (split payment) for a payment method. * Open the session. * Create an order assigning the child contact and pay using this method * Close the session. * Accounting payment for this session will be assigned to child partner opw-5121710
When a form section is hidden during rendering, it now stays blank instead of showing the word “undefined”. This prevents broken-looking layouts in full-size forms, especially where action buttons are generated separately.
Original PR description
Currently if the root node of a template is invisible at compile time the "new root" will contain the word "undefined" in plain text. Instead if we skip rendering the root for whatever reason, the new root should simply be an empty t node. This lead to issues in full-size forms specifically as the controller compiles the buttons separately. Meaning if the buttons div was evaluated to be invisible for whatever reason you would get "undefined" where stats buttons normally go. task-5322823
This fix ensures the vendor on-time rate shown in the smart button matches the graph. It now uses the original purchase order quantity instead of a delivery-side quantity that could be inflated after split or duplicated receipts, so the percentage is accurate for partial deliveries.
Original PR description
**Steps to reproduce:** 1- Install the purchase_stock module. 2- Create a new PO with a new vendor. 3- Add new one product in the purchase order line with quantity > 1. 4- Confirm the PO and go to…
**Steps to reproduce:** 1- Install the purchase_stock module. 2- Create a new PO with a new vendor. 3- Add new one product in the purchase order line with quantity > 1. 4- Confirm the PO and go to the generated receipt. 5- Validate the receipt with less than the ordered quantity, by choosing no backorder. 6- Duplicate the receipt for the remaining quantity and validate it. 7- In vendor form view, the On-time Rate value shown in the smart button differs from the value in the graph. **Issue:** https://github.com/odoo/odoo/blob/e7da32fe67cfe78bc6da8bf5d36a7c584763e3bb/addons/purchase_stock/report/vendor_delay_report.py#L26-L42 - The On-time Rate shown in the smart button does not match the graph. **Example:** - PO Line ordered qty: 10 - First receipt validated: 6 (no backorder) - Duplicated receipt validated: 4 - In vendor form view inside On-time Rate Smart button - Total quantity coming: 14 (incorrect) - Expected total qty for calculation: 10 (from PO line) - On-time delivery rate calculated: **71.43%** - Expected On-time delivery rate: **100%** **Cause:** - The report uses `product_qty` from the stock move. - When a receipt is duplicated and the demand quantity is manually set, `product_qty` is recomputed from this demand value. This leads to a mismatch between the PO line quantity and the aggregated stock move quantities. **NOTE:** In `test_02_vendor_delay_report_partially_cancelled_purchase_order`, added the line:: `purchase_order.order_line.flush_recordset()` - Because we were taking the `partner_id` from the `Purchase Order line` is a stored related field. - The computed value first lives in Odoo’s cache. - It is not written to the database until a flush occurs. - If we immediately call something like _read_group() (which queries the database directly), it won’t see the cached value — only what is persisted in the DB. **Solution:** - Use the purchase order line quantity instead of the stock move’s `product_qty` to ensure consistent and accurate On-time Rate calculation. opw-4991367
This update refreshes the LinkedIn API version used by the social integration. It was necessary because the previous version was retired, helping keep LinkedIn publishing and account features working as expected.
Original PR description
This commit updates the linkedin version header so that we can use the version of the API. Our actual version was recently sunset, needing the change of version to be done. task-5271712 Forward-Port-Of: odoo/enterprise#99759
Odoo now handles rejected Egypt e-invoice download responses more gracefully. If the external service returns an unexpected response, the system catches the error properly instead of showing a traceback to users.
Original PR description
Before this commit: Steps 1) When clients try to download e-invoice for ETA 2) If ETA rejects the request, Odoo fails to parse to JSON 3) a JSONDecodeError exception is raised 4) Odoo doesn't catch it and a traceback is raised => A JSONDecodeError is raised but actually it's not json.decoder.JSONDecodeError, it's actually requests.exceptions.JSONDecodeError as mentioned here https://requests.readthedocs.io/en/latest/api/#requests.JSONDecodeError After this commit: If the request is rejected and Odoo failed to parse the response to JSON the exception is catched properly. opw-5241411 opw-5272195
Anchor links with the “Open in New Window” option now behave as expected and open in a new tab instead of staying in the same page. This fixes a confusing issue that could make users think the setting was not working.
Original PR description
Steps to Reproduce: 1. Create an anchor link for any dropped snippet. 2. Insert the link through the link popover. 3. Enable the "Open in New Window" option. 4. Click on Save. 5. Click on the link. Issue: Even though the "Open in New Window" option is enabled, the page scrolls in the same tab instead of opening in a new window and scrolling to the targeted view. Reason: When an anchor link has target="_blank", `ev.preventDefault()` was still being called, which prevented the browser from performing its default behavior of opening the link in a new tab. Fix: Removed `ev.preventDefault()` for such links, as the expected behavior is to open them in a new tab whenever target="_blank" is set. Additionally, the offcanvas mobile-specific logic has been removed, as it is no longer necessary now that `ev.preventDefault()` is no longer used. task-5104027
The German DATEV export now includes bills where the tax total was manually adjusted, so the exported amounts match what users see in Accounting. This prevents incorrect totals in the audit file and keeps the export aligned with the final invoice values.
Original PR description
- Install Accounting and `l10n_de_reports` - Switch to a German company - Create a bill: * Price: `100.00` * Taxes: `19%` - Edit the tax total with the pencil button - Go to "Accounting / Reporting / Audit Reports / General Ledger" => The tax amount is the one that has been edited manually - Download `Datev DATA (zip)` - Open `EXTF_accounting_entries.csv` file The total amount in the file is the one before the edition of the tax amount. The Datev data depends on `price_total` field of the invoice lines, but this field is not updated when the tax amount is edited manually. We now check the total by adding `price_total` of each invoice line and the total amount defined in `tax_totals` field. If there is a difference, compute the delta for each tax group and split it between all the lines where a tax of that group is used. Ticket [link](https://www.odoo.com/odoo/project.task/4951488) opw-4951488
This fix allows users to create a reordering rule for a product in one company even if that product has a kit bill of materials in another company. It prevents an incorrect validation error by only checking kit rules that belong to the same company, so company-specific settings no longer interfere with each other.
Original PR description
Steps to reproduce: - Create a storable product "P1" - Add a kit BoM restricted to Company A - Switch to Company B - Try to create an orderpoint for "P1" in Company B Issue: A validation error is raised: "A product with a kit-type bill of materials cannot have a reordering rule." Cause: The check did not consider the company of the BoM, so kit BoMs defined in other companies incorrectly blocked orderpoint creation. Solution: Add the company condition in the BoM search domain to ensure that only BoMs belonging to the same company (or global ones) are considered. opw-5158491
This change ensures product labels always use the correct currency when calculating prices. It prevents certain label templates from showing incorrect prices due to a parameter mix-up.
Original PR description
Description of the issue/feature this PR addresses: In product label reports, calling _get_product_price with positional arguments may lead to incorrect parameter binding (e.g. currency_id being interpreted as uom). This can cause wrong prices to be displayed in labels in some cases. Current behavior before PR: Some label templates pass currency as a positional argument. This may result in wrong prices being shown depending on argument order. Desired behavior after PR is merged: Label templates always pass currency as a keyword argument, ensuring correct price computation and preventing mismatches. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr My CLA signature is being added in this PR: https://github.com/odoo/odoo/pull/236586
Documentation and clarification updates
This update refreshes the corporate contributor agreement record for Moduon. It matters for keeping legal and administrative documentation current and aligned with the company’s latest information.
Original PR description
@moduon MT-12696