Daily updates from Odoo
Friday, August 14, 2026
21 changes · master
New functionality added to Odoo
Belgian payroll now supports the withholding tax exemption for qualifying investments in aid zones. This helps employers apply the temporary 25% reduction for eligible newly created jobs and include the required 274.81 reporting in payroll declarations and reports.
Original PR description
Implement support for the Belgian withholding tax exemption regarding investments in aid zones. Employers benefit from a temporary 25% reduction in withholding tax remittance on eligible remunerations for newly created jobs. Changes: - Add `l10n_be_is_aid_zone` flag on employee,version models. - Update 274.XX calculation logic to isolate Nature 81 bases and apply the flat 25% rate. - Add "Aid Zone (274.81)" tab in the UI and include its totals in the main Exempted Amounts summary. - Update (XML payload and XLSX report) to include the new 81 code block. Task: 6352132
Enhancements to existing features
Spreadsheet dashboards across several business areas have been visually standardized so figures display with consistent sizing, spacing, and backgrounds. A new Employee appraisal dashboard has also been added, and translated dashboard text now displays correctly without being compressed.
Belgian payroll now alerts users when an employee's bank account is invalid. This helps payroll teams catch payment issues before processing salary payments, reducing failed transfers and manual follow-up.
Original PR description
This commit adds a warning message in the Belgian payroll module when an employee's bank account is invalid. task-6458596
Calendar events are now matched to projects or tasks using their direct “linked to” relationship before falling back to customer history. This makes suggested timesheets more accurate, especially when calendar meetings are tied to specific project or helpdesk work.
Original PR description
…ojects via the 'linked to' field Before this commit: - Calendar events are matched based on the most timesheet project of the partners. After this commit: - Calendar events are matched to projects/tasks via the "linked to field" before looking to partners projects. task-6238332
The timesheet Timeline view now displays assistant suggestions in true chronological order instead of sorting them by title. Users can also see each suggestion's start time, making it easier to review and enter work accurately.
Original PR description
Forward-Port-Of: odoo/enterprise#126238 Forward-Port-Of: odoo/enterprise#122862
Standard VAT checks are now available from the start across Odoo, reducing inconsistent behavior between setups. EU online VIES VAT checks are separated into an optional accounting-related module, making configuration cleaner for companies that need them.
Original PR description
Previously, both standard offline VAT validation and VIES VAT validation were implemented within a single module, `base_vat`. This led to several issues: 1. Since VIES depended on `account`, it made…
Previously, both standard offline VAT validation and VIES VAT validation were implemented within a single module, `base_vat`. This led to several issues: 1. Since VIES depended on `account`, it made it difficult to use even the standard VAT validation independently. 2. `base_vat` had to be explicitly added as a dependency in all localization modules (l10n), which was redundant because a single dependent module would install it globally anyway. 3. Standard VAT validation was not available from the start at a global level, leading to inconsistencies in validation behavior before and after module installation. With this PR: 1. The standard offline VAT validation is moved to `base`, making it available globally from the beginning. 2. The VIES VAT validation is separated into a new module, `l10n_eu_account_vies`. This module can be enabled via the `vat_check_vies` option in settings. task-5428948 Community PR - https://github.com/odoo/odoo/pull/259784 Upgrade PR - https://github.com/odoo/upgrade/pull/10014 IAP PR - https://github.com/odoo/iap-apps/pull/1609
The light user role now automatically includes a standard set of permissions for employees, including access to Planning, Appointments, and Referral features. This helps ensure employees receive consistent baseline access without extra manual setup.
Original PR description
Since there is a new light user role (and group) that will be set for each employee, this role must come with a package of privileges. Additional default groups are added to the light user: - Planning: User - Appointment: User - Refferal: User: Referral only See related Community PR for more details. Task-6112938
Payroll dashboard warnings now load through a single continuous request instead of many separate requests. This keeps warnings appearing as they are ready while reducing repeated server work, improving responsiveness and efficiency for users.
Original PR description
The dashboard warnings were loaded with multiple RPC calls (one per warning). The main issue with this behavior is the cache that stays cold => more queries are done for the same result at the end. Here we keep this behavior: see all warnings as soon as they are computed, on the dashboard, without blocking the user. But instead of the N rpc, there is one request, to get a stream of warnings. task-6422228
The time off Gantt view now keeps the full month visible for employees with flexible working schedules, making planning more stable and easier to read. New time off entries also avoid applying default hours that could overwrite an employee’s actual schedule.
Original PR description
- Display the full month for employees with flexible schedules to keep the month view stable. - Remove default hours from the creation payload to avoid overriding the employee's actual schedule. Task: 6346363
AI agents now use Odoo's website scraping service to collect content from URL sources instead of relying on basic local page parsing. This should make URL-based knowledge more reliable, avoid duplicate fetching across agents, and better organize how different source types are indexed.
Original PR description
Move URL source content extraction to use the IAP website scraper instead of fetching and parsing pages naively. Introduce two new models to support this: `ai.web.page`, which stores the scraped content of a URL and is shared by every AI agent source pointing to that URL so a given URL is only ever fetched and stored once regardless of how many agents source it, and `ai.web.scraper.batch`, which submits URL batches to the scraper, polls for their results, and dispatches them back to the model that requested them once they reach a terminal state. The change also removes the local HTML extractor, adds the required cron and access rules, and adapts source creation/reprocessing so binary, knowledge, and URL sources each follow their own indexing flow. Knowledge sources' content extraction is now using html2plaintext. task-id-6052079
Financial reports now present company information more clearly, reduce clutter in report headers, and format negative currency amounts correctly. The depreciation schedule and multi-ledger PDF filters were also adjusted so reports are easier to read and avoid duplicate "Local GAAP" labels.
Original PR description
Before this commit: - The depreciation schedule report displayed the currency symbol. - Company details were positioned below the company logo. - Unit options (e.g., Thousands, Millions) were displayed in the top-right options header. - Selecting only "Local GAAP" in the multi-ledger filters caused it to appear twice in the generated PDF. - Negative amounts for currencies with a 'before' position (e.g., '$') were formatted incorrectly as "$ (1)". After this commit: - Removed the currency symbol from the depreciation schedule. - Relocated company details to the right side of the logo. - Removed unit options from the top-right header - Fixed the multi-ledger filter to ensure "Local GAAP" appears only once in the PDF. - corrected the negative amount formatting for 'before' position currencies to "($ 1)". Community PR: odoo/odoo#281909 Task-6113583
The Call Debrief view now makes better use of larger displays by showing video and transcription side by side when both are available. It also adjusts more smoothly in full-screen mode, making call review easier and more comfortable across devices.
Original PR description
This PR improves the Call Debrief experience across screen sizes and adapts the UI by: - Use a two-column layout on larger screens when both video and transcription are available. - Make the layout adapt correctly in full-screen mode. task-6328684 Requires: - https://github.com/odoo/odoo/pull/272719 Forward-Port-Of: odoo/enterprise#122029
Resolved issues and error corrections
This fixes an accounting transfer issue where journal entries could be off by one cent when transferring a percentage to a destination account. The destination line now uses the exact amount removed from source accounts, helping ensure generated entries stay balanced.
Original PR description
Before this commit, _get_transfer_move_lines_values computed the amount for the last destination line from the global transferred balance, instead of reusing the amount already removed from the source accounts. The two values are rounded independently and can differ by a cent whenever the removed amount comes from more than one rounded source, producing an unbalanced journal entry. Removing that condition the last destination line always absorbs the remainder fixes it. Steps to reproduce: 1. Transfer model with 2 source accounts and 1 destination line at 15%. 2. Post moves for the period: account A balance 395.88, account B balance 252.16 (total 648.04). 3. Run `action_perform_auto_transfer()`. Before: source lines -59.38 (395.88 * 15%) and -37.82 (252.16 * 15%), destination line +97.21 (648.04*15% rounded) -> entry off by 0.01. After: destination line takes the exact remainder, 97.20 -> balanced. OPW-6443928 Forward-Port-Of: odoo/enterprise#126877
Subscription product tiles in the online shop now calculate discounted recurring prices from the correct subscription plan price, not the one-time sale price. This prevents customers from seeing misleading monthly prices when a pricelist discount applies to a recurring plan.
Original PR description
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the…
Steps to reproduce: =================== 1. Create a subscription product, allow one-time sale, sale price 5 2. Add a recurring price 10/month 3. On the pricelist, add an advanced rule: -10% for the monthly plan 4. Open the shop page and look at the product tile Cause: ======= On the /shop page, the subscription price displayed on a product tile is computed by `_get_sales_prices`. The cart has no plan selected yet at that point, so `request.cart.plan_id.id` is empty and was passed as `plan_id` to `_compute_price`. In `product.pricelist.item._compute_base_price`, the recurring base price is only looked up when a `plan_id` is given: if rule_base == 'list_price' and product.recurring_invoice and plan_id: ... # find the recurring rule -> base = recurring price With `plan_id` empty, that branch is skipped and the percentage rule falls back on the product's one-time `list_price` instead of the recurring price. Example: one-time price 5, recurring price 10/month, pricelist rule -10% on the monthly plan. => Tile showed 4.5/month (5 * 0.9) instead of 9/month (10 * 0.9). Solution: ========= The chosen pricing already targets a plan, so pass `pricing.plan_id.id` to `_compute_price`, matching what the product page does in `_get_additionnal_combination_info`. opw-6307398 Forward-Port-Of: odoo/enterprise#126259 Forward-Port-Of: odoo/enterprise#120872
Fixed an issue where Australian payroll could skip unused leave balances when processing multiple employees at once. Each payslip now checks leave allocations for the correct employee, helping ensure termination or final pay calculations include the right leave amounts.
Original PR description
`_l10n_au_get_unused_leave_by_type` compared leave allocations to `self.employee_id` while looping payslips. On a multi-recordset that is the whole employee set, so the match never holds and unused leave is skipped. Use `payslip.employee_id` so each payslip keeps its own allocations. task-6458480 Forward-Port-Of: odoo/enterprise#127330
VoIP contact searches now recognize phone numbers even when users type or receive an automatically added country code. This makes keypad suggestions and contact lookup more reliable and shows matched numbers in a clearer, user-friendly format.
Original PR description
Before this fix, the keypad's callee suggestions only matched the search term against the raw `phone` field of contacts. When the user input was automatically prefixed with a country code (e.g. +86), the match could fail if the stored phone number lacked the international prefix. Now `phone_sanitized` is also sent to the frontend via the Store, and the callee suggestion matching falls back to the E164 sanitized number when the raw phone field does not match. Task-6290760 compr https://github.com/odoo/odoo/pull/278018 Forward-Port-Of: odoo/enterprise#127553 Forward-Port-Of: odoo/enterprise#124797
When payroll users include additional unpaid payslips in a SEPA payment file, those payslips are now correctly marked as paid after using the payment confirmation action. This prevents payroll records from incorrectly remaining in a validated but unpaid state after payments are generated.
Original PR description
Steps to reproduce: - Open the payment report wizard on a payslip or a pay run - Tick "Include Unpaid" and keep the extra payslips selected - Generate the SEPA file, then click "Mark as Paid" Issue: the extra payslips listed in the file stay in state "validated". Cause: mark_as_paid() paid payslip_ids, while the file is built from unpaid_payslips. Fix: pay the payslips that are actually listed in the file. Task 6428919
Customers can now use Order Again for rental products even when their cart already has a changed rental period. The system reuses the cart's existing rental dates, preventing a false conflict that previously stopped the item from being added.
Original PR description
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview…
Steps to reproduce: --- - Install the `website_sale_renting` module. - Create a rental product, place an order for it with customer as `Administrator`, and confirm the order. - Open the order preview and click `Order Again`. - In the cart, modify the rental period. - Go to My Account > Your Orders, open the sales order, and click `Order Again` again. Issue: --- - Clicking Order Again a second time does nothing and - The following error is logged in the terminal: `You cannot mix different rental periods in the same order.` Root cause: --- - When the user clicks `Order Again`, the `/my/orders/reorder` route calls `add_to_cart`[1], which in turn invokes `_cart_add`[2]. If no rental dates are provided, `_cart_add` computes default rental dates based on the product's rental periodicity [3]. - However, when the current cart already has a rental period set, these computed dates differ from the cart's existing rental period. As a result, the rental consistency check detects the mismatch and prevents the product from being added to the cart. Solution: --- - When the current sale order already has a rental period set, reuse those dates instead of computing default ones. This ensures the product is added using the existing cart rental period and avoids the false conflict. [1]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/reorder.py#L63-L76 [2]: https://github.com/odoo/odoo/blob/bb9fcbb062887ab6b1c4c17870201d789afa9dbc/addons/website_sale/controllers/cart.py#L134-L141 [3]: https://github.com/odoo/enterprise/blob/a39da12a4a85d749235d59a05ebd67b91f9867b0/website_sale_renting/models/sale_order.py#L60-L64 opw-6357001 --- Forward-Port-Of: odoo/enterprise#125481
Meal voucher reports now use the original voucher value when correcting postponed vouchers from a prior period. This prevents employees or employers from being charged using a newer meal voucher amount for vouchers that were actually issued at an older value.
Original PR description
**Purpose:** -In case of postponed Meal vouchers, it may happen that the value of (patronal part + employee part) change. -Example: - June → MV amount 8 € - July → MV amount 10€ -Employee received too many MV in June because some absences where encoded after the order of the MV. -In that case, it will be postponed on July but the employee will be charged for a MV of a value of 10€ while he received meal voucher of 8€. **Proposed Solution:** -The total has been adjusted by considering the original value for _meal_voucher_amount_ in case of postponed MV.
The Belgian payroll report now uses the previous quarter's contract when a mobility budget balance is paid after the current contract no longer includes that budget. This prevents the declared amount from incorrectly showing as zero, improving payroll compliance and reporting accuracy.
Original PR description
When the mobility budget balance is paid on a contract that no longer carries a mobility budget, fall back to the previous quarter's contract to declare the correct amount instead of 0. Task-6384786 Forward-Port-Of: odoo/enterprise#127786 Forward-Port-Of: odoo/enterprise#127318
Fixed an issue where users without certain accounting permissions could be blocked from confirming sales orders when a Studio approval rule referenced a restricted related field. The approval check now runs with the right elevated access so valid approval workflows continue without unexpected access errors.
Original PR description
continuation of [PR](https://github.com/odoo/enterprise/pull/121856) Issue: Inside _get_approval_spec filtered_domain is called a few times and due to a related field that calls an access rights group that the user who used the action isnt apart of is blocked by the filtered_domain. To Replicate: 1) Install studio, sale, Accounting and make sure "account_followup" is installed 2) create a related field on the sales.order form related to "customer -> follow up status" 3) Save 4) Create a "Studio Approval Rule" (studio.approval.rule) with a domain using the new related studio field -> method : "action_confirm" -> approver:admin 5)create a test user with no accounting access rights 6) in an incognito browser try and create a sales order, and then confirm it. it will throw the access rights error Solution: Go one up the stack where _get_approval_spec is called and add a syudo for those calls opw-6316069 Forward-Port-Of: odoo/enterprise#127412