Daily updates from Odoo
Navigate
Branch
Monday, July 6, 2026
376 changes
9 changes
Enhancements to existing features
Uzbekistan financial reports now include Russian translations alongside Uzbek. This helps businesses in Uzbekistan use the reporting module more easily in a market where Russian is commonly used for business communication.
Original PR description
Uzbekistan's business environment requires Russian in addition to the official Uzbek language to ensure adoption. While localizations typically activate only statutory languages, Central Asian market realities justify this exception. task-6229114 -- I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/enterprise#122717 Forward-Port-Of: odoo/enterprise#120250
Resolved issues and error corrections
Belgian payroll now correctly accounts for loss on commissions when an employee takes sick leave without a certificate and the case is eligible. This helps ensure payroll calculations reflect the right compensation rules and reduces manual corrections.
Original PR description
Sick time off without certificate should grant loss on commissions if relevant Forward-Port-Of: odoo/enterprise#122807
The My Timesheet view now uses the current employee's work schedule when marking unavailable days. This helps employees see accurate non-working days and avoid entering time on days they are not scheduled to work.
Original PR description
To reproduce: ============= - modify Mitchel Admin's working schedule and remove a day of work - open timesheet app as Mitchel Admin - the removed day is not grayed out as unavailable Porblem: ======== the method `get_unavailabily` was handling only the case when calling it with `groupby=employee_id` otherwise it returns the company's unvailability Solution: ========= when the "My Timesheet" action is opened, the method `get_unavailabily` is now called with a specific context key, allowing to return the current user's unavailability instead of the company's one. opw-5949236 Forward-Port-Of: odoo/enterprise#122936 Forward-Port-Of: odoo/enterprise#113984
Opening the Manufacturing employee planning view no longer fails when the database includes employees from multiple companies. The view now only loads employees for the currently active company, preventing cross-company access errors and allowing planners to continue scheduling work orders.
Original PR description
Issue ----- When there are employees in different companies, opening the Work Order planning view causes an access error. Steps to reproduce ----- - Create 2 companies - Create an employee in each company - Go to Manufacturing > Planning > Employee Planning > Acces error Cause ----- The error happens in `_gantt_unavailability` when trying to browse the employee list https://github.com/odoo/enterprise/blob/5ddef3263d4d9788b894ea465fb183e53d4c9e89/mrp_workorder/models/mrp_workorder.py#L696 This function is called by `get_gantt_view` when loading the page. The list of ids come from https://github.com/odoo/enterprise/blob/5ddef3263d4d9788b894ea465fb183e53d4c9e89/mrp_workorder/models/mrp_workorder.py#L639 We can provide a domain to restrict the search to the current company instead. ----- Ticket: opw-6302105 Forward-Port-Of: odoo/enterprise#120831
Sales commission plans now prevent adding a salesperson whose start date is after the plan's end date. This helps keep commission periods consistent and avoids invalid sales compensation setup.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#118289
This update aligns a rental-related employee payroll setting so it behaves consistently across employee records and their versions. It prevents related automated checks from failing, helping maintain payroll data reliability without changing day-to-day user workflows.
Original PR description
The readonly value inconsistency between l10n_hk_rental_id field in the employee's model and the one in the version's model was provoking some tests to fail. Related runbot error: https://runbot.odoo.com/odoo/error/241956 task-6306032
Users who choose to handle notifications inside Odoo will now be alerted in their inbox when a requested signature is completed. This helps request senders stay informed without relying on email notifications.
Original PR description
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign*…
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign* (`sign`) 2. Sets the current user's notification preference to "Handle in Odoo" (`inbox`) 3. Create a sign request and send it to Marc Demo 4. As Marc Demo, sign the request 5. **The user who sent the sign request did not receive a notification to notify them that the request was signed.** ## Fix This is a partial backport of both https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda (saas-18.2) and a related fix https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 (19.0). Before the first commit, users would not receive inbox notification when sign requests would be completed. ## Note to reviewer The issue only occurs in 18.0, as it is fixed by https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda in 18.2, but we can backport the fix from https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 from 18.2 to 18.4 if desired. opw-6251702 Forward-Port-Of: odoo/enterprise#122740 Forward-Port-Of: odoo/enterprise#120740
Expected hours are no longer shown for employees who do not have a fixed or average working schedule. This avoids confusing targets such as 0 or 24 hours in the Timesheet Assistant and systray while still showing the employee's total logged hours.
Original PR description
**Steps to reproduce:** 1. Create an employee without a fixed working schedule. 2. Configure the employee with variable hours per day, per week, or no working hours at all. 3. Open the Timesheet Assistant or the Timesheet systray. 4. Observe that expected hours are displayed (over 0h 00m or over 24h 00m). **Cause:** Expected working hours were always computed and displayed, even for resources without a fixed schedule. **Fix:** Only compute expected working hours when the employee has a fixed or average schedule, and rely on the computed working hours to control the display of expected hours while keeping total hours always visible. task-6321760 Forward-Port-Of: odoo/enterprise#122232
This fix ensures the recruitment reports app includes the required component for cohort-style views during installation. It prevents setup failures in specific automated installation scenarios, improving reliability for deployments and upgrades.
Original PR description
installing hr_recruitment_reports with the --ski-auto-install flag causes an error. The error happens because it does not explicitly depend on web_cohort while displaying a cohort view. task-6352888 runbot_error-237854 Forward-Port-Of: odoo/enterprise#122432
19 changes
Enhancements to existing features
Budget reports now use the same profitability criteria as analytic profitability views when selecting analytic accounting lines. This helps make budget figures more consistent with profitability reporting, improving confidence in financial analysis.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636 Forward-Port-Of: odoo/enterprise#121760
Resolved issues and error corrections
Field service projects created from sales orders now use the customer’s delivery address, helping teams work with the correct onsite contact/location. The change also prevents an incorrect default sales line from blocking creation of field service projects based on templates.
Original PR description
FIX 1: industry_fsm_sale: set delivery address on project customer] ----------------------- **Steps to reproduce:** - Create a product: - Product Type: Service - Service Tracking: Create on Order…
FIX 1: industry_fsm_sale: set delivery address on project customer] ----------------------- **Steps to reproduce:** - Create a product: - Product Type: Service - Service Tracking: Create on Order (project) - Project Template: FSM type project template - Confirm a sale order with this product - Check the generated project customer **Issue:** The customer's delivery address is not set on the generated project. **Fix:** Set the delivery address as the project customer when creating the project. [FIX] industry_fsm_sale: remove default sale line in fsm projects ------------ **Steps to reproduce:** - Install industry_fsm_sale - Create a project template of fsm type - Create a sale order (service-type product) - Confirm the sale order - Create a project and select the fsm-type project template - Create the project **Issue:** - SQL constraint is triggered, preventing project creation. **Fix:** - If the project template is of fsm type, remove the default sale line from the context. task-5074893 Forward-Port-Of: odoo/enterprise#114523 Forward-Port-Of: odoo/enterprise#95920
The invoice outstanding payments widget now displays payments in descending order by date, with a secondary ordering by ID. This makes it easier for users to understand the most recent payments first and reduces confusion when reviewing invoices.
Original PR description
Before this commit: The invoice outstanding payments widget was not sorted by date globally, which could lead to confusion for users when viewing the widget. After this commit: This commit adds a sorting mechanism to ensure that the payments are displayed in descending order based on their date and ID. opw-6254080 Forward-Port-Of: odoo/enterprise#121642
Users who choose to handle notifications inside Odoo will now be notified when a signature request they sent is completed. This prevents missed updates and helps request owners follow up without relying on email notifications.
Original PR description
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign*…
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign* (`sign`) 2. Sets the current user's notification preference to "Handle in Odoo" (`inbox`) 3. Create a sign request and send it to Marc Demo 4. As Marc Demo, sign the request 5. **The user who sent the sign request did not receive a notification to notify them that the request was signed.** ## Fix This is a partial backport of both https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda (saas-18.2) and a related fix https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 (19.0). Before the first commit, users would not receive inbox notification when sign requests would be completed. ## Note to reviewer The issue only occurs in 18.0, as it is fixed by https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda in 18.2, but we can backport the fix from https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 from 18.2 to 18.4 if desired. opw-6251702 Forward-Port-Of: odoo/enterprise#122740 Forward-Port-Of: odoo/enterprise#120740
The recruitment reports app now correctly declares the component it needs to show cohort-style reporting views. This prevents installation failures in automated setups and helps keep deployment processes smooth.
Original PR description
installing hr_recruitment_reports with the --ski-auto-install flag causes an error. The error happens because it does not explicitly depend on web_cohort while displaying a cohort view. task-6352888 runbot_error-237854 Forward-Port-Of: odoo/enterprise#122432
Stripe card expenses now correctly recognize merchant category codes that fall within configured ranges, reducing incorrect authorization errors. Declined Stripe expenses also avoid duplicate refusal messages, keeping expense records clearer for users and finance teams.
Original PR description
# [FIX] hr_expense_stripe: Fix MCC ranges Context: Since 3e52d875 when receiving an authorization whose MCC fits in a range we would not find it in the search. This is logical yet we return an error before checking properly mcc codes with range included After this commit: This will also check that the authorization MCC exist if we don't directly find the range. We move the "not found" error after that check too The forgotten tests have been added into the overrides opw-6185961 opw-6288399 # [FIX] hr_expense_stripe: Fix double refusal of expenses Context: When an expense is created through a declined stripe authorization, the expense is refused twice, resulting in a duplicated refusal message After this commit: Do not refuse already refused expenses Forward-Port-Of: odoo/enterprise#121474
Delivery insurance configured for Envia shipping methods is now sent in the format expected by Envia. This ensures insured shipments can generate the required insurance documents during delivery validation.
Original PR description
Issue ----- Insurance set on the delivery method is not correctly being communicated to Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - 10% insurance - Create a MX client - Create a product (with some weight) - Create a SO using the delivery method & confirm - Validate the picking > No insurance pdf is being printed Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#118966
Sales commission plans now reject salesperson start dates that fall outside the plan's effective period. This helps prevent incorrect commission setup and avoids downstream calculation issues caused by invalid dates.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#118289
The Timesheet Assistant now hides the Add option and avoids opening prefilled timesheet forms for projects that do not allow timesheets. This prevents users from trying to log time on projects where time tracking has been disabled.
Original PR description
Before this commit, the Timesheet Assistant would display the "Add" button and attempt to prefill timesheet forms for activities matched to projects where the `allow_timesheets` setting was set to `False`. This commit updates the Timesheet Assistant logic to evaluate the project's configuration. When an activity is matched to a project that has `allow_timesheets=False`: - The "Add" button is hidden from the suggestion list. - The system prevents prefilling the timesheet creation form. Task: 6306203 Forward-Port-Of: odoo/enterprise#120890
Archived folders linked to projects are now protected from automatic trash deletion, preventing cleanup jobs from failing. Project document links also open the correct view when the related folder is archived, so users are not sent to an empty location.
Original PR description
## Problem
When a folder linked to a project gets archived, the documents trash autovacuum unlinks it along with regular trash. That triggers the constrains . This happens whether the project is still active or also archived.
## Fix
Add one leaf on the GC domain: `('project_ids', '=', False)`. so the document is not deleted if linked to a project
Forward-Port-Of: odoo/enterprise#122323
Forward-Port-Of: odoo/enterprise#117692This fix prevents Belgian payroll setup from crashing when optional student payroll structure data has been removed or is unavailable. It helps administrators load demo data or continue configuration without encountering a blocking error.
Original PR description
This error occurs because the XMLID `structure_type_student` does not exist. Steps to reproduce: - Install `l10n_be_hr_payroll` module without demo data - Set Company `Country` to `Belgium` - Search `Structure Types` and delete `Belgian Student` and it's related `Structures` - Active debugger > Settings > load Demo data Traceback: `ValueError: External ID not found in the system: l10n_be_hr_payroll.structure_type_student` Solution: We pass `False` when the XMLID `structure_type_student` cannot be found. sentry-7323712470
The timesheet assistant now captures time spent in Odoo apps even when it cannot link the activity to a specific project, task, or ticket. These activities appear as separate suggestions, helping users record more of their actual working time accurately.
Original PR description
This PR adds support for tracking time spent in the Odoo apps in the assistant, for when we can't trace URLs to a project/task/ticket. The activities detected this way are marked as key events, such that each appears as an individual line in the assistant suggestions. With this, most of the time users spend working in their Odoo database should be reflected in the assistant suggestions. Task-6250449
Field service interventions now require both a start and end date before they can be completed. Send and publish actions are also hidden when no date is set, helping teams avoid incomplete or incorrectly scheduled work.
Original PR description
After this PR: - Both dates are required to use the 'Complete' action button on an intervention - If the start date is set on an intervention, the end date should be required (and vice versa) - We hide the 'Send' and 'Publish' buttons if there is no date set task-6234939
This fixes issues that caused Sign-related automated checks to fail when demo data or prior activity existed in a local database. It makes the checks focus only on the records created for each test, improving reliability without changing customer-facing signing behavior.
Original PR description
Version: 19.0 `test_sign_request_notification`, `test_gc_removes_orphan_roles_and_dummy_items` ,`test_sign_tour` and `test_sign_tour_without_sign` fail locally when you run them on a db with demo…
Version: 19.0
`test_sign_request_notification`, `test_gc_removes_orphan_roles_and_dummy_items` ,`test_sign_tour` and `test_sign_tour_without_sign` fail locally when you run them on a db with demo data installed, after doing some manual testing/ operations on it.
- `test_sign_request_notification` builds `completion_mail_to_user` by searching `mail.mail` for any email addressed to the admin's address. If admin had received any other email before this test ran, it got counted too, so the assertion on `len(completion_mail_to_user)` became wrong. We now also filter by subject matching `sign_request.reference`, so it only counts the email this test's own sign request actually generated.
- `test_gc_removes_orphan_roles_and_dummy_items` relies on the helper `_get_signer_and_item_gc_context` to count dummy sign items (page < 0). That helper searched `sign.item` with no domain at all, so any dummy item left behind by a different template got added to `non_active_item_ids` and broke the `len(non_active_item_ids) == 4` check. We now scope that search to `template_id = sign_template.id`, so it only counts items belonging to the template created in the test.
- `sign_tour` had a step targeting `.o-autocomplete--dropdown-item:contains('Administrator')` in the signer autocomplete. After installing demo data the admin user is named `Mitchell Admin`, so the tour failed on databases using that name. Both contain 'Admin', so the trigger now matches on that instead.
taskid- 6329037
Forward-Port-Of: odoo/enterprise#121878Fixed an issue where printing the Journal Audit report could add a completely blank final page when the global tax summary was not included. This makes exported PDFs cleaner and avoids confusion for accounting users reviewing or sharing audit reports.
Original PR description
Steps to reproduce: 1. Set the active company as My Company (san francisco) 2. Navigate to Accounting > Review > Journal Audit 3. Remove all journals from the report except Bank and Misc. 4. Use the PDF action button to print the report. 5. The last page of the report is completely empty. https://drive.google.com/file/d/1otpniJgt1UNCe2hrUBwqIK58dGuXpu8T/view?usp=sharing This commit ensures that the Journal Audit report does not have blank pages when the global tax summary section is not present. It uses some features of QWeb outlined in the following docs article: https://www.odoo.com/documentation/19.0/developer/reference/frontend/qweb.html#loops opw-6224670 Forward-Port-Of: odoo/enterprise#121068
The Belgian salary package calculation now excludes holiday allowance from the mobility budget cap and handles 13th month payments more accurately. It also includes recent commissions, helping employers calculate compliant and fair mobility budgets for employees.
Original PR description
https://lebudgetmobilite.be/fr/6-quel-est-le-montant-du-budget-mobilite#remunerationtotalebrute Simple and double holiday allowance should not be not accounted in the total brut remuneration for the cap of 20% for the mobility budget. 13th month should not be included if it is paid in warrants. This commit fixes the max mobility budget amount computation by multipling the wage by 12.08 instead of 13, as we remove the simple holiday allowance. Ratio = 12 months + 13th month - Simple holiday allowance (0.92 month) Also, Commissions should included: Sum the commissions on payslips of the last 12 months for this employee. MB_Budget = monthly_wage * ratio / 5 + commissions Task-5948733
Batch bank reconciliations now combine matching early payment discount lines before posting. This prevents the tax return from overstating the discount base when multiple invoices with the same tax are reconciled together, improving accounting report accuracy.
Original PR description
Steps to reproduce 1. Create two customer invoices that share the same VAT tax, with a payment term granting an early payment discount. 2. Create one bank statement line whose amount equals the sum…
Steps to reproduce 1. Create two customer invoices that share the same VAT tax, with a payment term granting an early payment discount. 2. Create one bank statement line whose amount equals the sum of both invoices' discounted totals. 3. From the bank reconciliation widget, select both invoices and validate in a single batch reconciliation. 4. Open Accounting > Reporting > Tax Return, switch the variant to "Group by: Account > Tax". Issue The cash-discount expense row shows a Net base column equal to twice the real discount base. The Tax column is correct. The bank-statement reconciliation paths (set_line_bank_statement_line, set_batch_payment_bank_statement_line, _reconcile_payments) loop over each invoice and call _apply_early_payment_discount one invoice at a time. Each call writes one discount base line and one discount tax line on the resulting bank entry, so when two invoices share the same tax the bank entry ends up with two pairs carrying the same (account, partner, currency, tax_repartition_line_id, tax_ids). The SQL that feeds the tax report at https://github.com/odoo/odoo/blob/d7d0efd39a65bfb6fee307b661cd2523a6b8231d/addons/account/models/account_move_line_tax_details.py#L100 matches every base line of a tax with every tax line of that tax inside the same move. With two pairs sharing one tax that turns two rows into four, and SUM(base_amount) doubles. The Tax column does not double because the same SQL redistributes each tax line's recorded amount across its matched rows so the totals still add back to the original tax. The payment register flow does not have this problem because it calls _get_invoice_counterpart_amls_for_early_payment_discount once with every invoice, and that helper already collapses duplicates with the merge key at https://github.com/odoo/odoo/blob/f3b317310b84edb073009f7d15d7fec002f3ccf0/addons/account/models/account_move.py#L5082-L5093 opw-6199906 Forward-Port-Of: odoo/enterprise#122747 Forward-Port-Of: odoo/enterprise#117743
Portal users can now archive or unarchive documents in approved system-managed flows that use elevated permissions. This restores compatibility for business processes that relied on those actions, while also avoiding errors when no documents are selected.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows did rely on it and we were lacking a way of supporting it. Task-6205627
Users without Payroll access can now open Belgian working schedules without encountering an error. The change adds an access check so payroll-specific reorganisation data is only read when the user has the right permissions.
Original PR description
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees…
**Steps to Reproduce:** 1)Create a database in v19.2. 2)Install the l10n_be_hr_payroll module. 3)Open the login user's profile and set the Payroll access rights to No (null). 4)Navigate to Employees → Configuration → Working Schedules. **Actual Result:** A traceback is triggered after opening the record. ```python Failed to read field resource.calendar.l10n_be_reorganisation_measure_ids You are not allowed to access 'BE: Reorganisation Measure.' (l10n.be.reorganisation.measure) records. This operation is allowed for the following groups: - Payroll/Assistant Contact your administrator to request access if necessary. ``` **Issue:-** The traceback is caused by the following commit introduced in v19.2 [here](https://github.com/odoo/enterprise/commit/e1092393ff99e9dad84ea8b9d6066e0bc61d6312) In this commit, a new computed field `l10n_be_reorganisation_measure_ids` was added on `resource.calendar`. The field is computed and store=true when the read function is called, and reads the data from the database at that time; The payroll doesn't have any access rights due to the error **Solution:** To fix this issue, a group access check is added inside the field Ticket:- 6245936
13 changes
Enhancements to existing features
The Uzbekistan reporting module now includes Russian translations for key financial reports, such as the balance sheet and profit and loss statements. This supports local business adoption by reflecting the practical language needs of companies operating in Uzbekistan.
Original PR description
Uzbekistan's business environment requires Russian in addition to the official Uzbek language to ensure adoption. While localizations typically activate only statutory languages, Central Asian market realities justify this exception. task-6229114 -- I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/enterprise#120250
UK VAT returns now guide users to file from the correct tax unit when their company belongs to one. When a tax unit is included in the return, Odoo uses the tax unit VAT number for HMRC connection and submission, reducing filing errors.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#122908 Forward-Port-Of: odoo/enterprise#107253
Budget reports now use the same profitability criteria as analytic reporting when selecting accounting lines. This helps finance teams see budget figures that better match analytic profitability views, reducing confusion when comparing reports.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636 Forward-Port-Of: odoo/enterprise#121760
Resolved issues and error corrections
The outstanding payments widget on invoices now lists payments consistently by newest date first, using the payment ID as a tie-breaker. This makes it easier for users to review recent payments and reduces confusion caused by mixed ordering.
Original PR description
Before this commit: The invoice outstanding payments widget was not sorted by date globally, which could lead to confusion for users when viewing the widget. After this commit: This commit adds a sorting mechanism to ensure that the payments are displayed in descending order based on their date and ID. opw-6254080 Forward-Port-Of: odoo/enterprise#121642
Stripe expense authorizations are now matched correctly when merchant category codes fall within configured ranges, reducing incorrect errors during card expense processing. Declined Stripe expenses also avoid duplicate refusal messages, making expense records clearer for users and approvers.
Original PR description
# [FIX] hr_expense_stripe: Fix MCC ranges Context: Since 3e52d875 when receiving an authorization whose MCC fits in a range we would not find it in the search. This is logical yet we return an error before checking properly mcc codes with range included After this commit: This will also check that the authorization MCC exist if we don't directly find the range. We move the "not found" error after that check too The forgotten tests have been added into the overrides opw-6185961 opw-6288399 # [FIX] hr_expense_stripe: Fix double refusal of expenses Context: When an expense is created through a declined stripe authorization, the expense is refused twice, resulting in a duplicated refusal message After this commit: Do not refuse already refused expenses Forward-Port-Of: odoo/enterprise#121474
This fix ensures the recruitment reports app includes the component it needs to display cohort views. It prevents installation failures in certain setup modes, making deployments smoother and reducing setup interruptions.
Original PR description
installing hr_recruitment_reports with the --ski-auto-install flag causes an error. The error happens because it does not explicitly depend on web_cohort while displaying a cohort view. task-6352888 runbot_error-237854 Forward-Port-Of: odoo/enterprise#122432
Fixed how shipment insurance is sent to Envia so insured deliveries can be processed as expected. This helps ensure customers using Envia delivery methods receive the correct insurance documentation, such as insurance PDFs, when validating shipments.
Original PR description
Issue ----- Insurance set on the delivery method is not correctly being communicated to Envia. Steps to reproduce ----- - Create a MX company - Set up Envia - Fedex Nacional Economico (ground) - 10% insurance - Create a MX client - Create a product (with some weight) - Create a SO using the delivery method & confirm - Validate the picking > No insurance pdf is being printed Cause ----- We are passing the insurance value as a `insurance` field on the shipment, which is not what the API expects. We should instead pass it in `additionalServices` as shown in the example of https://docs.envia.com/docs/additional-services#how-to-add-services-to-a-shipment ----- Ticket: opw-5254952 Forward-Port-Of: odoo/enterprise#118966
Sales commission plans now block salesperson start dates that fall outside the plan's effective period. This prevents incorrect commission setup and helps keep plan assignments aligned with approved date ranges.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#118289
Users who choose to handle notifications inside Odoo will now be alerted in their inbox when a signature request they sent is completed. This helps request owners track completed documents without relying on email notifications.
Original PR description
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign*…
## Issue When a user sets their notification to "Handle in Odoo" (`inbox`) and a sign requested is completed, they do not receive the expected notification. ## Steps to reproduce 1. Install *Sign* (`sign`) 2. Sets the current user's notification preference to "Handle in Odoo" (`inbox`) 3. Create a sign request and send it to Marc Demo 4. As Marc Demo, sign the request 5. **The user who sent the sign request did not receive a notification to notify them that the request was signed.** ## Fix This is a partial backport of both https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda (saas-18.2) and a related fix https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 (19.0). Before the first commit, users would not receive inbox notification when sign requests would be completed. ## Note to reviewer The issue only occurs in 18.0, as it is fixed by https://github.com/odoo/enterprise/commit/463d6a2aae536356e6dee6b902f2e881dbc4fbda in 18.2, but we can backport the fix from https://github.com/odoo/enterprise/commit/41395dba4fd31222f5fd9fc94a84c977cf9334f9 from 18.2 to 18.4 if desired. opw-6251702 Forward-Port-Of: odoo/enterprise#122740 Forward-Port-Of: odoo/enterprise#120740
This update fixes Sign app test failures that could happen when demo data or prior manual activity was present. It makes automated checks focus only on the records created by each test, helping developers validate changes more reliably without affecting business features.
Original PR description
Version: 19.0 `test_sign_request_notification`, `test_gc_removes_orphan_roles_and_dummy_items` ,`test_sign_tour` and `test_sign_tour_without_sign` fail locally when you run them on a db with demo…
Version: 19.0
`test_sign_request_notification`, `test_gc_removes_orphan_roles_and_dummy_items` ,`test_sign_tour` and `test_sign_tour_without_sign` fail locally when you run them on a db with demo data installed, after doing some manual testing/ operations on it.
- `test_sign_request_notification` builds `completion_mail_to_user` by searching `mail.mail` for any email addressed to the admin's address. If admin had received any other email before this test ran, it got counted too, so the assertion on `len(completion_mail_to_user)` became wrong. We now also filter by subject matching `sign_request.reference`, so it only counts the email this test's own sign request actually generated.
- `test_gc_removes_orphan_roles_and_dummy_items` relies on the helper `_get_signer_and_item_gc_context` to count dummy sign items (page < 0). That helper searched `sign.item` with no domain at all, so any dummy item left behind by a different template got added to `non_active_item_ids` and broke the `len(non_active_item_ids) == 4` check. We now scope that search to `template_id = sign_template.id`, so it only counts items belonging to the template created in the test.
- `sign_tour` had a step targeting `.o-autocomplete--dropdown-item:contains('Administrator')` in the signer autocomplete. After installing demo data the admin user is named `Mitchell Admin`, so the tour failed on databases using that name. Both contain 'Admin', so the trigger now matches on that instead.
taskid- 6329037
Forward-Port-Of: odoo/enterprise#121878The Journal Audit PDF report now avoids adding an empty final page when no global tax summary is included. This keeps printed audit reports cleaner and reduces confusion for accounting users.
Original PR description
Steps to reproduce: 1. Set the active company as My Company (san francisco) 2. Navigate to Accounting > Review > Journal Audit 3. Remove all journals from the report except Bank and Misc. 4. Use the PDF action button to print the report. 5. The last page of the report is completely empty. https://drive.google.com/file/d/1otpniJgt1UNCe2hrUBwqIK58dGuXpu8T/view?usp=sharing This commit ensures that the Journal Audit report does not have blank pages when the global tax summary section is not present. It uses some features of QWeb outlined in the following docs article: https://www.odoo.com/documentation/19.0/developer/reference/frontend/qweb.html#loops opw-6224670 Forward-Port-Of: odoo/enterprise#121068
The voice transcript 'share by email' action now posts the transcript summary only to the record the user is viewing. This prevents summaries from being accidentally added to other records of the same type, keeping customer and lead histories accurate.
Original PR description
Issue: Voice transcript 'share by email' button would get post the transcript summary to the chatters of all records of a given model. Steps: 1) install crm and ai 2) activate openai and gemini by…
Issue: Voice transcript 'share by email' button would get post the transcript summary to the chatters of all records of a given model. Steps: 1) install crm and ai 2) activate openai and gemini by saving the api keys inside settings. 3) create 2 crm leads in order a) lead 1 and lead 2 4) go into lead 1 and in the description then type in '/voice-transcription'. 5) Go into the 'transcription' section of the voice transcription 6) type something and save 7) then click 'start recording' 8) click 'stop recording' - it doesn't need to actually record 9) wait to process 10) click the 'share by email' button 11) check lead 2 for a message created (there shouldnt be one) 12) go back to lead 1 and click the 'share by email' button 13) check lead 2 again and a second message appears. that is becuase it makes a new mail.compose.message with res_ids of a list of multiple crm.lead.id (e This was fixed in 19.2+ with the pr https://github.com/odoo/enterprise/pull/115978. But it didnt make it in 19.0 and 19.1 Fix: default_res_ids: model?.config.resIds, -> default_res_ids: [model?.config.resId] take the single record id instead of the list res_ids opw-6285883 Forward-Port-Of: odoo/enterprise#121021
International UPS shipments now use the customer’s main commercial address as the Sold To address when appropriate, preventing incorrect commercial invoices when delivery and billing details differ. If UPS requires the Sold To country to match the delivery country, Odoo falls back to the delivery address and warns the user so the shipment can proceed with clear visibility.
Original PR description
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- -…
Issue ----- When making an international delivery to a partner with different invoice and delivery addresses, we send the delivery address as the `Sold To` address as well. Problematic case 1 ----- - Create a belgian company - Setup UPS - Create a French customer - Add a different french delivery address - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > Commercial invoice `Sold To` uses the delivery address Solution for case 1 ----- Use the delivery address' `commercial_partner_id`. This leads to another issue in some edge cases... Problematic case 2 (caused by case 1 fix) ----- - Create a belgian company - Setup UPS - Create a French customer - Add a delivery address in Switzerland - Create a product (with some weight) - Create a SO (with UPS delivery) to the customer & confirm - Validate the transfer > UPS error `The Sold To party's country code must be the same as the Ship To party's country code with the exception of Canada and satellite countries.` Solution for case 2 ----- Default back to delivery address for the `Sold To` field when countries don't match, as this is a limitation of the UPS API. Warn the user, either on the SO or the transfer itself (if no SO). Warning looks like this (on SO): <img width="1914" height="716" alt="image" src="https://github.com/user-attachments/assets/f7aa73c4-f24c-42da-8f3e-6a58765ef020" /> ----- Ticket: opw-6200263 Forward-Port-Of: odoo/enterprise#121340 Forward-Port-Of: odoo/enterprise#118031
9 changes
Enhancements to existing features
Budget reports now use the same profitability criteria as analytic profitability reporting. This helps finance teams compare budget and profitability views more consistently and reduces discrepancies in reported analytic line data.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636 Forward-Port-Of: odoo/enterprise#121760
UK VAT return filing now warns users when their company belongs to a tax unit and automatically switches the report to that tax unit after confirmation. When filing to HMRC, the system uses the tax unit's VAT details instead of the individual company's, reducing filing errors for grouped companies.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#122908 Forward-Port-Of: odoo/enterprise#107253
The Sendcloud delivery option formerly labeled "Use Batch Shipping" is now called "Use Multicollo". This aligns Odoo terminology with Sendcloud wording, reducing confusion for users configuring shipments.
Original PR description
In order to avoid confusion for the customer, "Use Batch Shipping" was renamed to "Use Multicollo".This way it is consistent with the terminology used by Sendcloud. task-6048477 Forward-Port-Of: odoo/enterprise#122133
Resolved issues and error corrections
The outstanding payments section on invoices now lists payments in a consistent newest-first order. This helps users quickly understand recent payment activity and reduces confusion when reviewing invoices.
Original PR description
Before this commit: The invoice outstanding payments widget was not sorted by date globally, which could lead to confusion for users when viewing the widget. After this commit: This commit adds a sorting mechanism to ensure that the payments are displayed in descending order based on their date and ID. opw-6254080 Forward-Port-Of: odoo/enterprise#121642
Commission plans now reject salesperson start dates that fall outside the plan’s effective period. This prevents invalid commission setup data and helps ensure sales compensation rules are applied consistently.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#118289
Task progress shading in the Gantt view now shows the correct completion level based on timesheeted hours. This makes project and field service planning clearer by preventing partially completed tasks from appearing almost empty.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#111270
Fixes an error that could occur when updating quantities on Field Service sales orders while message-based automation rules are active. The change keeps background messaging compatible with automation, so users can adjust catalog quantities without interrupting their workflow.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#119542Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior year of work. This improves accuracy for employees with shorter service periods and adds test coverage for related edge cases.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903 Forward-Port-Of: odoo/enterprise#122580
This update prevents a batch payment test from running in setups where the Accountant app is not installed. It avoids false test failures caused by different accounting behavior, improving reliability of quality checks without changing business functionality.
Original PR description
`test_payment_state_after_invoice_edition_without_journal_entry` test fails when `accountant` module is not installed. The test is specific to a case where there is no journal entry linked to a payment. However, when `accountant` module is not installed, a journal entry is always linked to the payment. runbot-941263 Forward-Port-Of: odoo/enterprise#123017
10 changes
Enhancements to existing features
The Sendcloud delivery option previously called "Use Batch Shipping" is now called "Use Multicollo". This aligns Odoo wording with Sendcloud terminology and helps customers better understand the setting.
Original PR description
In order to avoid confusion for the customer, "Use Batch Shipping" was renamed to "Use Multicollo".This way it is consistent with the terminology used by Sendcloud. task-6048477 Forward-Port-Of: odoo/enterprise#122133
Budget reports now use the same profitability classification as analytic profitability reporting when selecting analytic accounting entries. This helps businesses compare budgets and profitability with more consistent figures across reports.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636 Forward-Port-Of: odoo/enterprise#121760
Resolved issues and error corrections
Sales commission plans now prevent adding a salesperson whose start date falls after the plan's end date. This helps avoid invalid commission setup and reduces downstream errors in commission tracking.
Original PR description
Version: 18.0 Steps to reproduce: - open sale commission plans and create a new plan with an effective period - go to the salesperson tab and add a salesperson - set the salesperson from date after the plan end date issue: salesperson period start date was accepted even if it was set after the plan end date fix: added validation to raise an error when the salesperson start date falls outside the plan effective period task id: 6241188 Forward-Port-Of: odoo/enterprise#118289
Task progress bars in the Gantt view now show the correct completion level based on logged timesheets and allocated hours. This prevents under-reporting progress visually, helping teams quickly understand task status in planning views.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#111270
This fixes an error that could occur when updating quantities on confirmed Field Service sales orders while an incoming-message automation rule is active. The change keeps background message handling compatible with automation, so users can adjust catalog quantities without being blocked by a crash.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#119542This fix prevents an internal payment test from running in a setup where its assumptions do not apply. It helps keep automated validation reliable without changing customer-facing payment behavior.
Original PR description
`test_payment_state_after_invoice_edition_without_journal_entry` test fails when `accountant` module is not installed. The test is specific to a case where there is no journal entry linked to a payment. However, when `accountant` module is not installed, a journal entry is always linked to the payment. runbot-941263
This fixes DHL delivery validation when shipments are processed from a company other than the main one. Commercial invoice numbers are now generated correctly, preventing DHL rejection errors for eligible international deliveries.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#118379
The barcode app now better identifies the existing owner of consigned stock when scanning delivery items, including products without lot tracking. This prevents duplicate stock records and helps deliveries use the correct available inventory.
Original PR description
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations >…
### Steps to reproduce: - In the settings enable: "Storage Locations" and "Consignment" - Create a storable product and put 1 unit in stock with a set owner - Go to the barcode app > Operations > Delivery Orders > New - Scan your product and validate #### > The owner was not set on the stock move line so that a new quant was created and updated in stock rather than using the available unit. ### Cause of the issue: The mechanism of prefilling an owner or a package in the barcode app is currently gate-kept behind the existence of a lot name: https://github.com/odoo/enterprise/blob/0be4f71de3420fb9b72fd4e70d48c6cbbbc0ecb4/stock_barcode/static/src/models/barcode_model.js#L1382-L1407 However, the option also make sense for none tracked products. ### Note: Performing the flow form the backend and adding quantity will generate the move line by setting the owner if possible since the quantity of a move is set via the back end, move lines are generated by looking at the existing quant data's: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2364 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2328-L2330 Setting the same owner on the new move line as on the quant we are going to reserve: https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L2337 https://github.com/odoo/odoo/blob/5d61c03b33c9a915684dd59656f8be7612956dd1/addons/stock/models/stock_move.py#L1715 Additional subtelties appearing when prefilling for non tracked product: 1. Currently the available quantity is not taken into account to determine if the the value provided to the prefilled is actually relevant, in particular if there is a quant with an available quantity of 0, it will be used as a valid value to prefill and it will parasit the prefill that could be done by other quants. 2. The location source used to determine the quants taken into account is not set on the first scan since the scan is performed without any existing line: https://github.com/odoo/enterprise/blob/4f0d25f9fe4ca8ff1b0ecd7900899a2a246ba888/stock_barcode/static/src/models/barcode_model.js#L1387 > This was not problematic with respect to tracked product since the product needs to be scanned prior to the lot, hence there is always a current line when the the lot is scanned. opw-6050657 Forward-Port-Of: odoo/enterprise#121996 Forward-Port-Of: odoo/enterprise#115021
A test for duplicating field service subtasks was updated so it no longer depends on an internal ordering that can vary. This helps keep automated checks stable and reduces false failures during development and releases.
Original PR description
Steps to Reproduce --- 1. Install industry_fsm_report. 2. Run the test test_subtasks_worksheet_template_id_duplicate Issue --- The test fails because it relies on positional index assertions (child_ids[0] and child_ids[1]). Since child_ids is now returned with the ordering (id desc), the subtasks are processed in a different order during copy, causing the assertions to no longer match the expected records. Fix --- Sort both the original and duplicated subtask recordsets by name. task-5966684
Hong Kong payroll now calculates payment in lieu of notice based on the employee's actual contract start date instead of assuming a full prior 12 months. This improves payroll accuracy for employees with shorter service periods and adds test coverage for related edge cases.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903 Forward-Port-Of: odoo/enterprise#122580
19 changes
New functionality added to Odoo
Adds Latvian VAT report attachments for domestic purchases, EU purchases, domestic sales/exports, and EU sales, plus an XML export covering the main report and attachments. This helps businesses prepare more complete Latvian VAT filings directly in Odoo with the required transaction detail and export format.
Original PR description
This commit adds 4 attachments to the Latvian tax report and an XML export for the tax report (including the attachments). The attachments are the following - PVN 1-I: domestic purchase / import -…
This commit adds 4 attachments to the Latvian tax report
and an XML export for the tax report (including the attachments).
The attachments are the following
- PVN 1-I: domestic purchase / import
- PVN 1-II: EU purchase
- PVN 1-III: domestic sales / export
- PVN 2: EU sale
The attachments give more details for the tax report.
The lines of the attachments are "transactions"
A "transaction" is identified by the move and the transaction type or document type.
The transaction type is given via a tax tag (see community PR).
- PVN 1-I: transaction type, move
- Small transactions (< 150€) are aggregated separately under transaction types 'V' or 'T'
independently of the move
- 'V': All small transactions of a partner in case the total of all their small transactions reaches 150€
- There is max 1 line per partner
- 'T': All small transactions that are not grouped under some 'V' line
- There is max 1 line like this; it has no partner information
- PVN 1-II: transaction type, move
- Small transactions (< 150€) are aggregated separately under transaction types 'V' or 'T'
(like PVN 1-I)
- PVN 1-III: document type, move and line in the main tax report
- All transactions with (document) type 'X' are aggregated on a single line
- Small transactions (< 150€) are aggregated separately under document types 'V' or 'T'
(like PVN 1-I)
- The line in the main tax report is ignored for 'X' and small transactions
- PVN 2: transaction type, move
- No aggregation is performed here
Only account move lines that are tagged with a transaction type (1-I, 1-II, 2)
or a relevant tag for the main report (1-III) are shown in the reports.
The tags `Rep` and `C (car)` only take 40% and 50% respectively of the
base amounts. The tax amount is assumed to be split correctly.
task-4251184
Forward-Port-Of: odoo/enterprise#84135Enhancements to existing features
The salary configurator now better supports language changes by ensuring previously untranslated terms can be translated automatically. This improves clarity for employees and HR teams using the tool in languages other than English.
Original PR description
Originally, some terms remain untranslated when chaging the language from English. Thus, those terms have been adjusted to adhere to automatic translation
UK VAT returns now warn users when the selected company belongs to a tax unit and guide them to file from the correct tax unit. HMRC connections and submissions use the tax unit VAT number when the return includes tax unit data, reducing filing errors.
Original PR description
BEFORE: - Before this commit, when the current company is a member of the tax unit, there is no blocking level error for the user to select the tax unit. - And the vat used while creating a connection to the HMRC or while sending a tax report to the HMRC is of the current company. AFTER: - After this commit, there is one blocking level error, which tells the user that the current company is part of a tax unit, and on confirmation, the tax unit will automatically be selected for the current report. - And if the return contains the data of a tax unit, then the vat set on the tax unit will be considered while establishing the connection and sending the tax report to HMRC. Task-5865605 Forward-Port-Of: odoo/enterprise#107253
The Sendcloud delivery option formerly called "Use Batch Shipping" is now called "Use Multicollo". This aligns the wording with Sendcloud terminology, reducing confusion for users configuring shipments.
Original PR description
In order to avoid confusion for the customer, "Use Batch Shipping" was renamed to "Use Multicollo".This way it is consistent with the terminology used by Sendcloud. task-6048477 Forward-Port-Of: odoo/enterprise#122133
Budget reporting now uses the same analytic profitability criteria as profitability analysis. This helps business users see more consistent figures between budget reports and analytic profitability views, reducing confusion when comparing performance.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636 Forward-Port-Of: odoo/enterprise#121760
Resolved issues and error corrections
Task progress bars in the Gantt view now show the correct amount of completed work. This fixes a display issue where partially completed tasks appeared almost empty, helping users better understand task progress at a glance.
Original PR description
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same…
Steps to reproduce: ------------------------------------------- 1. Install the Timesheet module with demo data 2. Go to any FSM task > set allocated hours to 20h 3. Fill the timesheet for the same task for 10h 4. Navigate to FSM > My Tasks > Gantt view Observation: ------------------------------------------- Look at the task on the Gantt chart. The shading is barely visible because it covers only 0.5% of the bar, not 50% Issue: ------------------------------------------- In the commit https://github.com/odoo/odoo/pull/137570/changes/4a93d9aee957dd3feb3db0cb69eb3b8f0f4a4683 The progress field computation was changed from storing percentage values (0-100) to storing decimal values (0-1). Specifically, the `_compute_progress_hours` method was modified. This change was made to standardize the progress field storage format, with the understanding that the UI layer would multiply by 100 when displaying the value. While most views (form, list, kanban, etc.) were updated to multiply the progress by 100 for display purposes, the Gantt view's pill progress bar was missed. Solution: ------------------------------------------- Overrides the `enrichPill` method to multiply the `_progress` value by 100 before it's passed to the template. This ensures the Gantt pill progress bars display correctly without modifying the core web_gantt module. Before --------------------------- <img width="268" height="368" alt="image" src="https://github.com/user-attachments/assets/6d35927f-bd3f-47fc-9101-e2e188d419b8" /> After: -------------------------- <img width="250" height="371" alt="image" src="https://github.com/user-attachments/assets/fe7133e0-26d1-4c5f-b903-48826fda9488" /> opw-6038983 Forward-Port-Of: odoo/enterprise#111270
This fix prevents an error when users update product quantities on confirmed field service sales orders while automated message rules are active. The system now safely suppresses unnecessary chatter messages without breaking automation, keeping sales order updates reliable.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#119542The Peppol settings now apply the right rule for when a purchase journal is required, especially when French PDP features are installed. This prevents non-French companies using Documents for Peppol imports from being blocked by an unnecessary journal requirement, and ensures imports go only to the selected destination.
Original PR description
Fixes the settings view for the account_peppol_purchase_journal_id. account_peppol, documents_account_peppol and l10n_fr_pdp all wants to use a specific condition for the required attribute of the view. With PDP especially, once l10n_fr_pdp is installed, the view forces the base condition, even if documents_account_peppol is installed, and even if the company is not even French. On a non-French company registered/registering on Peppol, the journal shouldn't be mandatory if documents_account_peppol_folder_id is set up. To ease things up, it is now using a computed field. task-6304479 Forward-Port-Of: odoo/enterprise#120717
This fixes an issue where multiple upsell orders linked to the same subscription product could lose their connection to the original subscription line. The change prevents duplicate product lines from being created on the parent subscription when upsells are confirmed, improving subscription billing accuracy.
This change updates the subscription sales process so scheduled invoicing can complete more reliably. It helps reduce missed or delayed invoices, supporting smoother recurring revenue operations.
This update fixes automated test checks for Web Studio's report editor. It helps keep internal quality controls reliable so future changes can be validated with less risk of hidden regressions.
Original PR description
https://github.com/odoo/odoo/pull/210144
This fix ensures DHL commercial invoices receive a valid invoice number when deliveries are validated from a company other than the main company. It prevents DHL shipment validation failures for international deliveries that require dutiable material documentation.
Original PR description
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end.…
Issue ----- When validating a delivery in a different company from the main one, the commercial invoice's number field is incorrect, which raises an error on DHL end. `content/exportDeclaration/invoice/number: expected type: String, found: Boolean` Steps to reproduce ----- - Create a Belgian company - Setup DHL - DHL Product D - Express Worldwide - Dutiable Material enabled - Create an amrican customer - Deliver a product to the american customer > Validation Error Cause ----- The field is populated in https://github.com/odoo/enterprise/blob/cf3c2fce8a6b7b2d7547d44a0e4423f887986d52/delivery_dhl_rest/models/dhl_request.py#L204 The problem is that `next_by_code` uses the company found in the env, whereas the sequence's company is the main one, so it is not found when doing https://github.com/odoo/odoo/blob/e3b0ca11d99b2ef819cdad68b169112cd73668b6/odoo/addons/base/models/ir_sequence.py#L287 ----- Ticket: opw-6171886 Forward-Port-Of: odoo/enterprise#118379
Chilean export invoice PDFs now keep the customs information table columns aligned even when origin or destination ports are not provided. This prevents package quantities from appearing under the wrong headings, improving document accuracy for exports.
Original PR description
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by…
### Issue: On Chilean export invoices, the customs information table may display data in the wrong columns When `Origin Port` or `Destination Port` is not set, the corresponding `td` is omitted by QWeb, causing the remaining columns to shift left This results in `Qty of Packages` appearing under `Origin Port` or `Destination Port` in the printed document ### Cause: `l10n_cl_port_origin_id` and `l10n_cl_port_destination_id` have no default value and are optional fields `t-out` on a falsy value omits the `td` entirely in QWeb, breaking the column alignment Adding `or ''` ensures an empty `td` is always rendered, preserving the table structure regardless of whether the fields are set ### Steps to reproduce: - Install `l10n_cl_edi_exports` and switch to CL Company - Create an Invoice (any customer, any line) - In the gear menu, select Print > Invoice PDF copy (Chile) Before the fix, `Qty of Packages` appears under `Origin Port` when neither port field is set opw-6304670 Forward-Port-Of: odoo/enterprise#121923
Project-linked document folders are no longer deleted by the automatic trash cleanup when they are archived. This prevents cleanup jobs from failing and keeps project document access reliable, including for archived projects.
Original PR description
## Problem When a folder linked to a project gets archived, the documents trash autovacuum unlinks it along with regular trash. That triggers the constrains . This happens whether the project is still active or also archived. ## Fix Exclude in the domain the documents attached to projects so the document is not deleted if linked to a project Forward-Port-Of: odoo/enterprise#122135
Fixes an error that could stop users from generating the Swiss payroll monthly summary spreadsheet. The report now handles its data correctly, allowing payroll teams to export the file without interruption.
Original PR description
RPC_ERROR Odoo Server Error ``` Occured on syctest18.sodexis.com on model l10n.ch.monthly.summary on 2025-07-07 08:00:08 GMT Traceback (most recent call last): File…
RPC_ERROR
Odoo Server Error
```
Occured on syctest18.sodexis.com on model l10n.ch.monthly.summary on 2025-07-07 08:00:08 GMT
Traceback (most recent call last):
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/http.py", line 2175, in _transactioning
return service_model.retrying(func, env=self.env)
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/service/model.py", line 161, in retrying
result = func()
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/http.py", line 2142, in _serve_ir_http
response = self.dispatcher.dispatch(rule.endpoint, args)
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/http.py", line 2393, in dispatch
result = self.request.registry['ir.http']._dispatch(endpoint)
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/addons/base/models/ir_http.py", line 340, in _dispatch
result = endpoint(**request.params)
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/http.py", line 759, in route_wrapper
result = endpoint(self, *args, **params_ok)
File "/opt/odoo/syctest18-odoo/src/18.0/addons/web/controllers/dataset.py", line 33, in call_button
action = call_kw(request.env[model], method, args, kwargs)
File "/opt/odoo/syctest18-odoo/src/18.0/odoo/service/model.py", line 83, in call_kw
result = method(recs, *args, **kwargs)
File "/opt/odoo/syctest18-odoo/src/18.0-Ent/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_monthly_summary.py", line 134, in action_generate_xls
line_values = self._get_line_values()
File "/opt/odoo/syctest18-odoo/src/18.0-Ent/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_monthly_summary.py", line 106, in _get_line_values
lines = [
File "/opt/odoo/syctest18-odoo/src/18.0-Ent/l10n_ch_hr_payroll_elm_transmission/models/l10n_ch_monthly_summary.py", line 108, in <listcomp>
for code, name, total in sorted(data.items(), key=lambda x: x[0][0]) # Sort by code
ValueError: not enough values to unpack (expected 3, got 2)
The above server error caused the following client error:
RPC_ERROR: Odoo Server Error
RPC_ERROR
at makeErrorFromResponse (https://syctest18.sodexis.com/web/assets/ea37c94/web.assets_web.min.js:2978:163)
at XMLHttpRequest.<anonymous> (https://syctest18.sodexis.com/web/assets/ea37c94/web.assets_web.min.js:2983:13)
```This fix changes how accounting-related demo data is prepared so it can work more reliably across multiple companies. It also gives better control over which accounts and journals receive demo records, avoiding unwanted setup requirements before the system is ready.
Original PR description
It gives more flexibility in various aspects: * we can install the demo on multiple companies, like already done for invoices etc * we have a finer choice on which accounts and journals we want to select (i.e. no asset on the Tax Adjustment journal) * we don't force installing a chart of accounts for the main company before the registry is loaded
The EU IoT scale certification module is no longer available for installation in this version. This avoids customers enabling a certification feature that will only be supported in major releases.
Original PR description
This PR makes the module non installable as the scale certification will only be available in major versions Upgrade PR: https://github.com/odoo/upgrade/pull/8537
Fixed an issue where the option to request signatures could disappear on some forms depending on how users opened them. The change ensures the option is shown whenever the form has the activity and message area needed to track signature requests.
Original PR description
### Issue: In #61250, the `SignRequestCogMenuItem` allowing for signature requests was removed from forms that did not have a chatter to track the actual requests. In 18.1, the method used to do this no longer works, so the button is now hidden on certain Views depending on how you access them. ### Solution: The conditions to meet haven't changed, so we can instead use the `chatter` itself. On form views with a chatter, the `Chatter` component will set the `fetchThreadData` to false, which we can check for. opw-4817423
Miscellaneous changes
Add in missing modules to tx/config where their pots were auto-added by the pot export sync. Note that new pot files that were only for model names (i.e. not user facing) are usually bridge modules with nothing to translate => they weren't added to the config file
Original PR description
Add in missing modules to tx/config where their pots were auto-added by the pot export sync. Note that new pot files that were only for model names (i.e. not user facing) are usually bridge modules with nothing to translate => they weren't added to the config file
12 changes
Enhancements to existing features
Budget reports now use the same profitability criteria as analytic reporting when selecting analytic entries. This makes budget figures more consistent with profitability views, helping teams compare performance with greater confidence.
Original PR description
Use the new field analytic_profitability in the conditions of the query to get the account analytic lines of the budget report task-4959636
Loan durations are now shown using "periods" instead of always saying "months," making the wording more accurate for different repayment schedules. The display spacing was also cleaned up so the duration reads more clearly to users.
Original PR description
Loan duration was always shown with 'months' and not validated against actual periods. This commit replaces it to 'periods' and corrects the spacing between the value and the duration label. task-5364297
The Sendcloud delivery settings now use the term "Use Multicollo" instead of "Use Batch Shipping". This aligns the wording with Sendcloud terminology, reducing confusion for users configuring shipment options.
Original PR description
In order to avoid confusion for the customer, "Use Batch Shipping" was renamed to "Use Multicollo".This way it is consistent with the terminology used by Sendcloud. task-6048477 Forward-Port-Of: odoo/enterprise#122133
Resolved issues and error corrections
Updating quantities from the sales catalog for field service products no longer causes an error when automated message rules are active. This keeps sales order updates running smoothly while still suppressing unnecessary chatter messages.
Original PR description
Steps to reproduce: ---------------------------------------- 1. Install `industry_fsm_sale` and `base_automation` modules 2. Create a product with: * Type: Service * Create on order: Task * Project:…
Steps to reproduce:
----------------------------------------
1. Install `industry_fsm_sale` and `base_automation` modules
2. Create a product with:
* Type: Service
* Create on order: Task
* Project: Field Service
3. Create an automation rule with:
* Model: Sales order
* Trigger: Incoming message
4. Create and confirm a sale order with this product
5. Add another product to the SO via the catalog view:
* Change the quantity to 2 or more
Observation:
----------------------------------------
Traceback occurs:
```
File '/home/odoo/src/odoo/addons/base_automation/models/base_automation.py', line 871, in _message_post
message_sudo = message.sudo().with_context(active_test=False)
AttributeError: 'bool' object has no attribute 'sudo'
```
Root Cause:
----------------------------------------
* Catalog qty change calls `set_fsm_quantity()` method
* Setting `fsm_quantity` triggers its inverse `_inverse_fsm_quantity()`, which writes the new qty to the SOL, but passes `fsm_no_message_post=True` in context to suppress chatter noise
https://github.com/odoo/enterprise/blob/ac5d670832a5e0db714c0bd056e1406b50bb4c17/industry_fsm_sale/models/product_product.py#L72-L83
* `sale.order.line.write()` detects a qty change on a confirmed order and calls `_update_line_quantity()`, which posts a message on the parent sale order
* FSM's `message_post` override sees the context flag and returns `False`
* When `base_automation` has an `on_message_received` rule on `sale.order`, it wraps `message_post` at registry load time. That wrapper calls `sudo()` on whatever `message_post` returns, Which was `False`
Solution:
----------------------------------------
Return `self.env['mail.message']` (empty recordset) instead of False, it's still falsy, but it's a proper ORM object that `sudo()` can be called on
opw-6276916
Forward-Port-Of: odoo/enterprise#119542Posting to Instagram could fail with an authorization error due to a recent change in Instagram/Facebook behavior. This fix adjusts how the post container is sent and allows more time for image uploads, making Instagram publishing more reliable.
Original PR description
Bug === When posting on Instagram, we get an Authorization error. From this thread: https://developers.facebook.com/community/threads/2162512441262894 the bug seems new, and the workaround is to give the container id in the GET parameters instead of in the URL path. Task-6254983
This fixes how Hong Kong payroll calculates payment in lieu of notice when an employee has not worked a full 12 months. The calculation now considers the employee's contract start date, reducing incorrect payouts and adding tests for special cases.
Original PR description
Currently, the calculation of the payment in lieu of notice is assuming the employee worked a whole 12 months prior to it being paid. This is of course not always going the be case, and when it happens our calculation is often incorrect. We update the salary rule to calculate a more accurate total days (which is no longer based on a fixed 12-month period but takes into account the contract's start date). We also now calculate the number of months more accurately by taking, once again, the contract's start date into account. Also adding a few test cases to test a bit more some special case we didn't yet test correctly. task-6348903
GIF-style media in Facebook feed comments now displays as a still preview instead of appearing missing. Users can click the preview to open the related video on Facebook, making comment content easier to review from Odoo.
Original PR description
Bug === When opening the comments modal of the feed view, the GIF images are not visible. Technical ========= The API does not return the GIF, it only returns the MP4 and the JPG. So we show the fixed image, and when clicking on it, it opens the video on Facebook. Task-6241607 Forward-Port-Of: odoo/enterprise#122832 Forward-Port-Of: odoo/enterprise#118619
This update restores code changes that were accidentally rolled back during an automated translation update. It helps keep affected point-of-sale, payment, delivery, and social media features working as intended without introducing new functionality.
Original PR description
The regular Weblate translation update reverted some code changes. This should normally not happen. We're reverting it back to the previous state. This partially reverts commit e427355b55661df120470bf4c18fb5acd8e47ebb.
Batch payment reconciliation now correctly handles supplier payments when exchange rates have changed between payment creation and bank reconciliation. This prevents unbalanced journal entry errors and allows invoices to be reconciled as expected, including proper exchange gain or loss entries.
Original PR description
Steps to reproduce 1. install account_accountant and account_batch_payment on a US / USD company 2. enable EUR as a currency. Create an exchange rate for the 1st day of the month of 1.1 3. create a…
Steps to reproduce 1. install account_accountant and account_batch_payment on a US / USD company 2. enable EUR as a currency. Create an exchange rate for the 1st day of the month of 1.1 3. create a bank journal with currency EUR, call it “Bank EUR” 4. create 2 supplier invoices in EUR, with amounts 100€ and 200€, dated 1st and 2nd day of the month, due date today 5. confirm the supplier invoices 6. pay the supplier invoices 7. put the payments in a batch 8. Imagine it’s the night, the cron updating the exchange rates run. Manually create an exchange rate for EUR dated today with value rate = 1.2 9. On the Bank EUR journal, create a transaction of -300€ dated today 10. Open the reconciliation screen for the Bank EUR journal, select the -300€ transaction, and on the batch payment tab, select the batch payment created in step 7 11. Click on the button validate **Expected result:** the invoices are paid and everything is reconciled, same as if we had selected the 2 invoices on the first tab instead of the batch payment. A journal entry is created on the Exchange Gain/Loss journal for each invoice. **Actual result:** you get an error message saying that the account move is not balanced. The problem is caused by the exchange rate used on the payments which is different from the rate on bank transfer. We fix this issue by recomputing the exchange rates on the payments when a batch payment is added to the reconciliation widget. Related support ticket: [5164405]
This fix restores support for specific document workflows where portal users need to archive or unarchive documents through elevated system actions. It helps prevent business processes from being blocked while keeping the general access restrictions in place.
Original PR description
In #116886, we fixed the blocking of portal users to (un)archive documents, but it appears that some flows relied on it and we were lacking a way of supporting it. Backport of #123015 Task-6205627
The Twitter social module now disables the reply button when Twitter rules do not allow replying, such as when the account is not mentioned or the post does not quote the account's tweet. This helps prevent failed replies and reduces the risk of automated responses being sent where they are not permitted.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524
This fixes an issue where Australian payslips could fail to compute if an employee's Income Stream Type was changed after the payslip was created. Payroll users can now recompute affected payslips without encountering an error, improving reliability during payroll processing.
Original PR description
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install…
When an employee's Income Stream Type is changed after a payslip has been created, computing the sheet for payslip will raise a traceback. Steps to reproduce the error: - Install ``l10n_au_hr_payroll_account`` module with demo data - Switch to ``My Australian Company`` company - Create a new payslip for ``Dennis Cactus`` Employee > Save - Go to Employees > Open the ``Dennis Cactus`` employee > In Payroll tab, Income Stream Type: Other specified payments > Save - Go back to payslip > click the compute sheet button Traceback: ```py KeyError: 'OSP' ``` https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L175-L178 The ``l10n_au_income_stream_type`` field on the payslip is a computed field that only depends on ``employee_id``. As a result, changing the employee's Income Stream Type does not trigger a recomputation of the corresponding field on existing payslip. So, when the ``payslip_ytd_totals`` field is computed, it uses the old value of ``l10n_au_income_stream_type`` field at [1], The resulting ``payslip_ytd_totals`` is then used to build the ``totals`` dictionary, and eventually, when the employee's current ``income_stream_type`` is used to access ``totals``, the mismatch key leads to the above traceback. https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll_account/models/hr_payslip.py#L75-L88 [1]: https://github.com/odoo/enterprise/blob/13e64e0cb7f566cbbb46109fe1c218eb7a14eead/l10n_au_hr_payroll/models/hr_payslip.py#L269-L272 solution: I added ``l10n_au_income_stream_type`` to ``add_to_compute()`` in ``compute_sheet()``. This ensures that stale values of ``l10n_au_income_stream_type`` on existing payslips are recomputed when the payslip sheet is computed. sentry-7536819310
9 changes
Security fixes and vulnerability patches
Website helpdesk forms now verify that preset hidden or injected values have not been changed in the browser before submission. This helps prevent users from tampering with customized form settings and makes altered submissions fail rather than silently accepting unsafe values.
Original PR description
Website forms can be customized using the website editor. These customized values are directly embedded in the form in a hidden input or injected via the `data-for` js mechanism. This commit ensures that these values are not modified by the client. It is necessary to generate the token after the rendering (in `_render_template`) because we don't know all the values to sign using only the stored arch. In fact, several values are dynamically computed during the rendering (see `data-for` and `t-att-data-values` tags attributes); these "js injected" values take precedence over the default values. It is better to raise an error than to correct the values when the form has been improperly modified by the end user. Task-6320608
Resolved issues and error corrections
Fixed an issue where loading the next page of a bank journal report could fail when the previous page ended with an unreconciled payment. Users can now continue paging through the report without encountering an error.
Original PR description
When a bank journal report is loaded in pages (with `load_more_limit`), the balance from the last line of a page is passed as `progress` to calculate the starting balance for the next page. If the last line is an unreconciled payment, it has no balance display, resulting in an empty string being passed as progress. When the next page attempts to use this progress to accumulate balances, it tries to add a float to a string, causing: `TypeError: can only concatenate str (not "float") to str` Steps to reproduce: 1. Setup a bank journal so that it has an unreconciled payment as the last line of the journal report page, and some bank transactions on the following page (use "load more limit", "sort by date" and date filter to achieve that). 2. Open the bank journal report and click "Load more" to load the next page. 3. A TypeError is thrown. Fix: Only update `next_progress` when processing non-unreconciled payment lines. opw- 6316508
Fixed an issue where weekly recurring planning shifts could incorrectly become open shifts instead of staying assigned to the selected resource. The system now checks whether the resource is genuinely overbooked before unassigning them, improving schedule accuracy and reducing manual corrections.
Original PR description
Steps to reproduce: ------------------------ 1. Install Planning 2. Create a slot for any resource spanning a full month (e.g., 05/01 08:00 - 05/31 17:00) 3. Enable repeat, set occurrence to "Week"…
Steps to reproduce: ------------------------ 1. Install Planning 2. Create a slot for any resource spanning a full month (e.g., 05/01 08:00 - 05/31 17:00) 3. Enable repeat, set occurrence to "Week" 4. Save and observe generated slots Issue: -------- Some recurring weekly slots are created as open shifts (resource_id = False) even though the resource is not actually busy during that period. Cause: ---------- The overlap check used to detect resource conflicts: https://github.com/odoo/enterprise/blob/a739c6c03c6629bad80f3fe61b1035ce156d59c6/planning/models/planning_recurrency.py#L122-L127 For a full-month slot (05/01 - 05/31), the first weekly recurrence starts on 05/08. Since 05/08 <= 05/31 (the original slot's end_datetime), the overlap condition evaluates to True and incorrectly sets resource_id to False. This issue does not reproduce for monthly recurrence because the next occurrence (06/01) is always greater than the current month's end_datetime (05/31), so the overlap condition evaluates to False. Fix: ------ Instead of stripping the resource on any overlap, we now compute total planned hours vs total available hours in the overlap window. The resource is only unassigned if it is truly overbooked (total_hours_planned > total_hours_in_overlap). NOTE: --------- This issue has been resolved from version 18 with this 079b0ba. opw-6144096
The Twitter social integration now disables the reply option when Twitter rules do not allow a response, such as when the account was not mentioned or the post does not quote one of its tweets. This helps prevent failed or inappropriate automated replies and reduces the risk of unwanted user outreach.
Original PR description
Purpose ======= To prevent LLM from spamming Twitter users, Twitter does not allow to reply to a tweet if we are not mentioned in it, or if the tweet does not quote one of our tweet. For that reason, we disable the reply button when needed. Task-5964524 Forward-Port-Of: odoo/enterprise#112128
Fixed an issue where clicking "Load More" in bank journal reports could fail when the running balance was blank. Users can now continue loading additional journal entries without the report crashing.
Original PR description
Steps to reproduce: - Install Accounting module - Accounting > Reporting > Journal Report > Ensure that the last line of the report has an empty balance column, and that the Load More button is…
Steps to reproduce:
- Install Accounting module
- Accounting > Reporting > Journal Report > Ensure that the last line of the report has an empty balance column, and that the Load More button is displayed immediately after it [image](https://www.awesomescreenshot.com/image/61045422?key=3ee9914f6472026aafa130253a9a32f9)
- Scroll down to the bottom of the Bank journal section and click load more
Traceback:
`TypeError: can only concatenate str (not "float") to str`
When opening a bank journal in the Journal Report and clicking "Load More" to fetch additional entries, the running balance calculation would crash and the report would fail to load further lines.
This was caused by the browser sending an empty string ('') as the current running balance instead of 0.0 when no cumulated balance had been rendered yet. Since the key already exists in the progress dict, the fallback default of 0.0 was never used, causing float arithmetic to fail on an empty string when updating the cumulated balance for each journal entry.
Fixed by sanitizing the progress values before use, converting any empty or missing balance values to 0.0, allowing "Load More" to work correctly on bank journal reports.
opw-6264616The timesheet grid now marks unavailable days using each employee's own working schedule instead of always relying on the company default. Approved personal time off is also shown as unavailable, making Timesheets consistent with the Time Off app and reducing scheduling confusion.
Original PR description
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different…
Steps to Reproduce --- - Create two different working schedules with different public holidays - Assign employees to specific working schedules - Set company default working schedule to a different schedule - Login as employee with specific working schedule - Navigate to Timesheets app -> My Timesheets - Observe public holidays and personal time-off displayed in the timesheet grid Issue --- - The timesheet grid displays unavailable dates (public holidays, weekends) from the company's default working schedule instead of the employee's assigned working schedule. - Personal time-off requests are not reflected as unavailable dates in the timesheet grid. Current Behaviour --- - Public holidays shown are always from the company's default working schedule, ignoring employee-specific working schedule assignments. - Employee's approved time-off requests don't appear as unavailable in the timesheet. Expected Behaviour --- - Public holidays should display based on the employee's assigned working schedule, with company schedule as fallback only when no specific schedule is assigned. - Employee's personal time-off requests should appear as unavailable dates. - This should align with Time Off app behavior. Fix --- - Included employee-specific work interval calculation with personal time-off requests. - Added support for contract-based calendar changes and calendar validity periods. - Implemented proper fallback when valid intervals are not found. task-4997080
Bank statement imports that contain only zero-amount transactions now show a specific error instead of being mislabeled as duplicates. This helps users understand the real issue with the file and take the correct action faster.
Original PR description
When importing bank statements, files containing only zero-amount transactions trigger the same generic "duplicate" UserError as files that have already been imported. We now explicitly check for zero-amount lines separately to raise a distinct UserError. opw-6237659
Vendor bills imported from Chilean electronic invoices now use the correct amount when the document is issued in a currency other than Chilean pesos. This prevents overstated or understated bills and helps accounting teams keep foreign-currency purchases accurate.
Original PR description
**STEP TO REPRODUCE** 1. Create a invoice to a chilian company, using another currency (for example UF, don't forget setup up a currency rate). 2. Confirm. 3. Download the xml in the chatter, and import it as a vendor bill. 4. Notice the imported bill amount are wrong (Pesos amount are used, with the currency being UF). opw-6269662
The Turkish Central Bank currency feed now uses the official selling rate instead of averaging buying and selling rates. This helps produce more accurate accounting and import valuation figures aligned with Turkish customs requirements.
Original PR description
## Short fix summary: The TCMB (Central Bank of Turkey) provider computed the exchange rate as an average of the buying and selling rates (`2 / (ForexBuying + ForexSelling)`). This is inaccurate for real accounting flows and does not follow Turkish customs regulation (Customs Law No. 4458, Art. 30), which requires the Central Bank's selling rate for goods import valuation. This now uses the selling rate (`ForexSelling`) only. task-6227500 I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr