Saturday, September 12, 2026
40 changes · master
Enhancements to existing features
Activity plans now default to being visible to all companies, making setup simpler for both single-company and multi-company users. Users can assign plans to any company they can access, and the activity scheduling screen has a small layout improvement for clearer badges.
Original PR description
Modify the `company_id` default on activity plans. In multi-company environments, it now defaults to `False` (Visible to all) instead of the current company. For single-company users, the selection used to be hidden, it is now visible and defaulting to `False`. Additionally, remove the `allowed_company_ids` domain from the form view. Users can now assign a plan to any company they have access to, not just the ones currently active in their session widget. Finally, fix a layout issue in the activity schedule wizard. The invalid `classname="pb-2"` attribute is replaced with `class="d-block"` on the `plan_id` field to ensure the activity type badges are properly forced onto the next row. Task-6563538
Users can now start online payment initiation directly from the payment record instead of navigating batch-payment details. This makes the payment workflow clearer, supports more eligible payment methods, and keeps payment status better aligned with the provider status.
Original PR description
*: account_batch_payment, account_iso20022, l10n_au_aba The previous flow exposed batch-payment internals to end users, which made routine payment actions harder to understand and increased friction in the payment workflow. Users should act from the payment itself, while technical batching concerns stay transparent and backgrounded. This change aligns the UX with that goal by keeping user actions on account.payment and using batch payments only as an implementation mechanism when needed. It also removes an unnecessary functional limitation where only sepa_ct could follow the direct initiation flow; all non-manual methods can now do so when their journal/method setup supports it. task-6326470
The payment flow is being streamlined so users can start bank-related actions directly from the payment record without seeing technical batch-payment details. The payment wizard and payment search views are also simplified, and an unnecessary “Sent” ribbon is removed from check printing payments.
Original PR description
Small improvements to the payment initiation UX. Major changes are done in the accompanying enterprise commit. task-6326470
Customers can now pay a single order using multiple payment methods by entering a custom amount during checkout or in the sales portal. This gives buyers more flexibility while keeping safeguards so sales orders are only confirmed when the required prepayment amount is actually received.
Original PR description
An amount input field is added to the payment form of payment methods to allow split payments. This allows the user to pay an order through multiple payment methods on: - eCommerce (checkout flow) - Sales' portal (except for downpayment and payment links) task-6359070 See also: - https://github.com/odoo/enterprise/pull/125129
This update aligns subscription portal and rental cart behavior with recent platform changes. It helps keep sales subscriptions and online rentals working consistently after related updates in the main Odoo system.
Original PR description
task-6359070 See also: - https://github.com/odoo/odoo/pull/275286
Appointment and POS Appointment screens now show more consistent information and controls, making it easier for teams to view, report on, and update booking statuses. The update adds Kanban, graph, and pivot views for appointments, improves popovers, and aligns the quick creation form for touchscreen POS use.
Original PR description
This PR alignes appointment and pos_appointment as the applications must display the same views and data as they have the same purpose: - The kanban view has been added in appointment to see the…
This PR alignes appointment and pos_appointment as the applications must display the same views and data as they have the same purpose: - The kanban view has been added in appointment to see the appointments per status and to easily update that attribute. A popover is displayed when clicking on kanban's records in order to show quickly essential information as in the gantt view. - The graph and privot views have been added in appointment to allow a better reporting. - The design of the popovers of the gantt and kanban views in appointment and pos_appointment have been updated. In appointment, the update of the appointment status is no longer done from a field but from buttons as they are more visible. As the popovers needs to display the same data, design and use the same logic, a unique popover as been created and used by those views. - The design of the form for the quick creation in pos_appointment has been aligned with the one in appoitment. To give more visibility to the appointment status, it can be updated using buttons in the footer. The form in pos_appointment is bigger than in appointment as it is used by touchscreens. Community PR: https://github.com/odoo/odoo/pull/287457 Upgrade PR: https://github.com/odoo/upgrade/pull/11154 Task-6185312
The quick event creation form in Calendar has been adjusted so it can share the same design with POS Appointment while still supporting the larger touchscreen layout needed there. This reduces duplicate styling and helps keep the user experience consistent across scheduling flows.
Original PR description
This PR adapts the code of calendar to improve the form for the quick creation of calendar events in pos_appointment. The design of the forms in calendar and pos_appointment must be the same. So o_calendar_event_form_quick_create should be used to avoid redefining it the css twice. However, this class is targeted to define the width of the modal and this one does not suit to the form in pos appointment as it must be bigger for the touchscreens. Therefore, a new class has been created to manage the size of the form in calendar and to make o_calendar_event_form_quick_create usable by pos_appointment. Enterprise PR: https://github.com/odoo/enterprise/pull/123700 Task-6185312
Belgian payroll can now apply legally required salary indexation alongside manual salary increases. The process also accounts for any applicable salary cap and uses the capped amount when calculating social contributions, helping payroll teams stay compliant.
Original PR description
It is now possible to increase salaries using legal indexation in addition to the manual increases. For a given year, the indexation rate is applied while taking the salary cap (if any) into account. The capped amount is stored in `l10n_be_capped_amount` and is used in the social contribution salary rule. task-6197739
Employees and finance teams can now dispute fraudulent Stripe expense card transactions directly in Odoo. The update adds dispute handling, evidence file upload and download, notifications, and testing support so companies can manage card disputes more efficiently.
Original PR description
If a transaction made is fraudulent, ... It can now be disputed. More details about dispute workflow with stripe can be found at https://docs.stripe.com/issuing/purchases/disputes. Add a widget to upload file to and download file from stripe such as dispute evidence, which will be able to be used for the other purpose. Buttons to win/lose a dispute are present in debug mode on the submit confirmation prompt to try those cases. task-4938982
Belgian payroll officers can now enter separate housing benefit amounts for social security contributions and withholding tax. This allows each payroll calculation to use the correct value when the ONSS base and tax base differ.
Original PR description
Before this commit, the housing benefit in kind had one single amount on the employee form. That amount was added to the ONSS base and to the withholding tax base at the same time, so both computations always used the same value. After this commit, the officer fills two amounts, one for ONSS and one for the taxes. Each one feeds only its own base, so the social contributions and the withholding tax can be computed on different values. taskid-6510566
Odoo now records where customer-facing messages come from, such as templates, views, mailings, or automated posting flows. This helps companies audit and review outgoing content more easily, supporting stronger brand control and compliance over customer communications.
Original PR description
RATIONALE In some cases (luxury, big corporate company) people want to be able to review all messages generated by Odoo that are sent to the customers. This is important when branding / copy writing…
RATIONALE
In some cases (luxury, big corporate company) people want to be able to
review all messages generated by Odoo that are sent to the customers.
This is important when branding / copy writing is considered valuable
(e.g. "Your ticket has been closed" → "We are happy to announce that your
care ticket ...").
Currently we have several ways of generating them
* using a mail.template (used either as template.send_mail() in code, either
due to tracked changes, either with manual usage of templates);
* message_post → post a body, and if recipients to notify by email content
is encapsulated in an email layout
-> can be manual (chatter), message_type being email (incoming email) or
comment (user input in chatter)
-> can be automatic (calling message_post in code), generally with
message_type being notification, auto_comment
* message_post using rendered body based on a qweb view (in code), see
message_post_with_source
* mail.mail manual creation → code only (as only admins can create mail.mail)
* message composer
-> may be used to post a message, on a single record or in batch, based
on a template or using custom body
-> may generate mail.mail in batch (standard mailing usage)
* mass mailing → uses message composer to generate emails
It is currently not possible to review through interface all content that
might be sent to clients automatically: mail.templates can be found and
modified, but strings inlined in code cannot (only through code or
customization). Views can be found but there is no easy way to find them
in the UI.
SPECIFICATION: AUDIT LOG
At least give a way to know a mail.mail was created automatically / manually
* when a template is used, keep mail_template_id on message. Note that if
content was modified manually, template_id is still propagated;
* when it is generated through a mass mailing, keep mailing_id on mail.mail
* when it is generated automatically by message_post in code → message_type
is 'notification', which is ok
* when it is generated by users → message_type is 'comment', which is ok
* add a flag on qweb views used in posting process so that we can filter and
find them easily. Add a menu entry below "Email Templates" to find them
Task-6368610 [mail] Track content source
Part of Task-6260135 [mail] Ability to review outgoing contentPayment completion now happens immediately after each payment is processed instead of waiting for separate background jobs or customer page actions. This should speed up backend workflows such as captures, refunds, invoices, subscriptions, and POS confirmations, while reducing customer wait times and keeping a fallback retry process for failures.
Original PR description
As of commit 4588e939, payment data records are queued and processed serially by a dedicated cron. This allowed payment requests to be isolated from the processing step and, by design, eliminated…
As of commit 4588e939, payment data records are queued and processed serially by a dedicated cron. This allowed payment requests to be isolated from the processing step and, by design, eliminated race-condition rollbacks on payment transactions. However, the post-processing remained a separate asynchronous step, still run on demand when customers reached the `/payment/status` page and from cron triggers scattered across provider and app modules for backend flows. This had several undesired side effects: - Backend business logic (captures, refunds, subscription invoicing, POS order confirmation, etc.) was forced to wait for a free cron worker or for the next scheduled run. - Customers had to wait out the 10-second timeout when the notification that should have triggered the redirect was missed (sent before the page had subscribed to its channel) or premature (sent before the transaction had been post-processed). - The post-processing cron had to run at a relatively high frequency, with only 10-minute intervals by default. - Transactions that had several state updates before they could be post-processed would only be post-processed for their last state change. - The extra step added overhead to the overall transaction processing cycle. This design was intentional, as it allowed payment requests and the processing step to be isolated from the much more failure-prone post-processing step. Indeed, it executed fragile business logic (e.g., posting invoices according to the journal configuration, sending emails) whose failures could have rolled back the transaction and replayed payment requests. Since this is no longer a risk, the post-processing can be unified with the processing step. This commit now synchronously post-processes transactions right after they are processed. If the post-processing fails, only that step is rolled back, and the transaction is left to the post-processing cron, which serves as a fallback and retry mechanism. Since the cron is now triggered whenever the synchronous post-processing fails, its interval is increased from 10 minutes to 24 hours. Satellite flows that confirm transactions without going through the processing (e.g., manual confirmation, refunds already executed on the provider side) now post-process immediately through the new `_try_post_process` helper method, and the asynchronous post-processing triggers scattered across provider and app modules are removed. The bus notification signaling that a transaction is processed is now sent only after post-processing is completed (succeeded or failed), and carries all the status values needed to redirect the customer. This, in turn, removes the synchronous trigger of the post-processing through a JSONRPC call to the `/payment/post_process` route, further reducing overhead in the payment flow. To avoid missing any notifications, they are now resent upon subscribing to their channel, allowing the redirect to rely on the websocket alone, with the timeout redirect kept only as a fallback. In addition, the retry window of the post-processing cron is reduced from 4 days to 24 hours. The longer window was meant to give slower providers time to send payment status updates, but processing such updates resets the transaction's `last_state_change` field anyway, so it was never necessary to keep retrying the post-processing for that long. If a transaction fails to be post-processed throughout the retry window, it is left for manual intervention. The cron is also modernized to use the new cron API to report its progress and to stop early when its time budget is exhausted. task-6240311 See also: - https://github.com/odoo/enterprise/pull/124474 - https://github.com/odoo/upgrade/pull/10846
VoIP calling is now more reliable across browsers, desk apps, and native SIP phones, with better matching of call records and fewer duplicate or missing calls. The update also adds phone provisioning by QR code, number request handling, improved user routing, and a recovery payload so phone service tenants can be rebuilt if accidentally deleted.
Original PR description
## voip: call correlation, number requests, user routing and tenant recovery Twenty commits on top of master. This is the client side of the phone_service work in odoo/iap-apps#1854 — the two land…
## voip: call correlation, number requests, user routing and tenant recovery Twenty commits on top of master. This is the client side of the phone_service work in odoo/iap-apps#1854 — the two land together, since the routing call and the user sync now carry new fields the service expects. ### Call records and events - **correlate on the conversation, not on a dual-purpose handle** — `control_handle` held the PBX conversation identifier for the Odoo provider and the SIP Call-ID for every other one, the browser collapsing the two into one value whose nature the server could no longer tell. The INVITE now sends `conversation_identifier` apart from `sip_call_id`; `get_or_create` matches the conversation first and the Call-ID through the legs after. The column stays — it still names a call for the softphone and the push payload — but nothing searches it. - **one live call per user and conversation** — a call is one user's point of view on one conversation, so a second ringing device joins it instead of opening a second record. Every event is processed in its own transaction and under REPEATABLE READ neither sees the other's insert, so find-or-create could not hold that on its own. - **give a call placed from a native SIP phone its own record** — a call dialled from Linphone left no trace: only the browser ever created a `voip.call`, and there is no browser. - **never settle a caller number from a reclassified leg** — Wazo swaps `caller_id_number` and `peer_caller_id_number` when it reclassifies a callee leg as internal on hangup, so the reversal that reads a ringing leg correctly reads a reclassified one backwards. - **log the whole webhook payload in debug**, behind an `isEnabledFor` check so `json.dumps` never runs on a normal server, **accept open-ended WAV data chunks** (both `0x7fffffff` and `0xffffffff`, which streamed audio uses and the decoder rejected), and **use UTC in astimezone**. ### User routing and preferences - **let users choose between being forwarded and being woken** — an explicit "On Disconnected" setting filling Wazo's chanunavail slot, taken the moment a dial finds no reachable SIP contact. It is the same decision as the wake-up token: with nowhere to forward, the PBX wakes the browser with a push; with a destination, it hands the call over at once. Settling that token is now entirely phone_service's business (odoo/iap-apps#1854), so voip stops generating, storing and sending a PBX credential — `voip_pbx_auth_password`, its reconcile cron and the `auth` object all go. What stays here is the user's own choice. - **forward disconnected calls to the phone by default** — mirroring the "no answer" fallback: the "On Disconnected" slot is seeded from the user's own number when it is valid, never replacing an explicit choice. The three forward slots also merge into a single "Forward" section. - **improve phone number flows** — regular users can request a number from the VoIP status menu, through a wizard and a mail template; purchase feedback, DID flags and destination selection are polished; and a SIP failure raised when a user cancels an outgoing call before its INVITE completes is no longer surfaced as an error, while genuine INVITE errors still are. - **use a busy hangup as the default busy fallback** — Hangup with the Busy cause and a 5s timeout when nothing else is configured. - **allow users to limit concurrent calls** — a "Ring Concurrent Calls" preference synchronized with the PBX, for queue and call group members who would otherwise ring several times at once. - **synchronize personal mailboxes with Wazo** — mailboxes created during user provisioning inherited the context that disables PBX sync and never reached Wazo. - **restrict voip.extension range** to 3 or 4 digits (100-9999), resolving a disagreement with the range phone_service configures on the tenant. ### Registration and provisioning - **one registration binding per softphone window** — Asterisk identifies a binding by its Contact URI alone (`pjsip_uri_cmp`, object named after the URI's MD5); neither `+sip.instance` nor `reg-id` is consulted, so every window of a user advertised the same binding. - **provision Linphone from a QR code** — a `linphone-config:` URI pointing at a signed URL serving a remote provisioning file. Linphone scans a provisioning URI, never credentials. - **let the Odoo provider's settings be edited** (the lock was view-only and cost nothing but keystrokes), and **drop the icon from the phone numbers Refresh button**. ### Number requests - **introduce number requests** — a search that returns no inventory left an administrator with no way to obtain numbers that need manual sourcing. A persistent DID number request, backed by the advanced order API of odoo/iap-apps#1854, carries a UUID for idempotent cross-service correlation, reuses the regulatory requirement groups, and syncs status, proposed numbers and comments into a provider-neutral form. Fulfilled numbers join the existing DID assignment flow and stay linked to their request. Creating or reviewing a request charges nothing; charges apply once the carrier fulfils it. ### Tenant recovery - **expose a tenant recovery payload** — a versioned description of the complete desired tenant configuration, served over a public route that only accepts a short-lived token signed with the client secret and scoped to recovery, so a Wazo tenant deleted by accident can be rebuilt.
Subscription-related payments are now handled immediately after payment details are processed, making follow-up actions more consistent and timely. A scheduled backup step remains for invoice-cron subscription payments so those transactions are still completed shortly after processing.
Original PR description
Payment transactions are now synchronously post-processed after their payment data records are processed (see the sibling commit in odoo/odoo). Since transactions whose subscription is flagged with `is_invoice_cron==True` are skipped by the post-processing, the existing cron trigger is kept to post-process them soon after. task-6240311 See also: - https://github.com/odoo/odoo/pull/276561 - https://github.com/odoo/upgrade/pull/10846
Odoo now tags the internal views used to generate chatter posts and outgoing customer messages, making it easier to identify where automated communication content comes from. This supports better review of customer-facing wording and branding across apps such as Helpdesk, Documents, Sign, Delivery Sendcloud, HR, and Data Cleaning.
Original PR description
RATIONALE In some cases (luxury, big corporate company) people want to be able to review all messages generated by Odoo that are sent to the customers. This is important when branding / copy writing…
Employee-paid expenses can now be connected to an existing supplier bill, such as one received through Peppol. This helps keep expense records and vendor bills aligned, reducing duplicate entry and improving traceability for accounting teams.
Original PR description
Link an existing bill to an expense paid by employee (e.g. if you receive the bill by peppol) task-6268863
The website AI can now create and configure web forms using the same guided setup as the standard website builder instead of hand-written form code. This helps prevent lost submissions, broken email routing, and form setup errors, making AI-generated website forms more reliable for business users.
Original PR description
The website builder agent could only touch forms by writing raw HTML, which produces forms that look right but lose submissions: field names that are not whitelisted degrade to plain text in the…
The website builder agent could only touch forms by writing raw HTML, which produces forms that look right but lose submissions: field names that are not whitelisted degrade to plain text in the record, a `send_mail` form missing its hidden `email_to` field gets no `website_form_signature` at render so every submission raises AccessDenied, and missing model-required fields fail at submit time. Teach the agent webforms as structured operations instead of markup: - "Get Webform Info" lists the available form actions and, per action, the model fields a form field can be bound to (from `get_compatible_form_models` / `get_authorized_fields`). - "Edit Webform" applies a validated list of operations (set_action, add_field, update_field, remove_field, set_success, set_recipient_email) through a new `website_edit_form` client tool. Every operation delegates to the community form option plugin (its builder actions and shared methods), so the resulting markup is exactly what the builder sidebar would produce and the save-time machinery (field whitelisting, default `email_to`, label/name sync) keeps working. The tool returns a per-operation report and the resulting form HTML, following the HTML apply report pattern. - "Apply HTML to Page" now refuses hand-written webform markup (form fields outside a form, webforms without a form-enabled `data-model_name`, unnamed inputs) and points the agent to the webform tool. Canonical form snippets and existing forms carried along in a zone replace pass untouched. - The Website Builder skill documents the workflow: insert a form snippet unchanged, then configure it with the webform tools. task-6251785
Employee expenses paid personally can now be linked to an existing supplier bill, such as one received through Peppol. This helps companies reimburse those expenses through payroll while keeping the original bill connected for clearer accounting and tracking.
Original PR description
Link an existing bill to an expense paid by employee (e.g. if you receive the bill by peppol), and reimburse it on salary task-6268863
Mailing list subscription and unsubscription flows now include extension points needed by marketing automation campaigns. The badge selection interface can also exclude specific choices, helping simplify upcoming marketing automation changes.
Original PR description
This PR is adding a few changes to web and mass_mailing so that we can refactor properly marketing_automation. ### [IMP] mass_mailing: add mailing list subscription handling This commit adds method calls to the subscribe/unsubscribe flow. These methods are used for marketing automation campaigns triggered by mailing lists. We are adding a flow for the subscription and a flow for the unsubscription so that they can be overridden in inheriting modules. ### [IMP] web: add blacklistedValues to badges_selection This commit adds the blacklisted_values option present on the filterable_selection widget. This option is useful in the case of the revamp of Marketing Automation as it allows us to limit the usage of JSON fields on an already complex model. task-3866422
The accounting dashboard now guides users more directly through e-invoicing setup and company data completion for sales journals. Companies can also mark themselves as not subject to VAT, with Belgian setups automatically using the right no-VAT tax behavior to reduce manual configuration and mistakes.
Original PR description
This PR introduces following changes: - Improves Account onboarding dashboard for Sales type Journals. It adds two actions for onboarding: "Activate Peppol" and "Set Company Data". - Introduces a new boolean "Not Subject to VAT" on Company. Which means that the company doesn't intend to apply VAT on sales / invoices. - For BE: If this boolean is checked, it disables all the active Sales Taxes and sets a new "0% NA" sale tax as a default tax for company. It also hides the tax column on move line for invoices and adds the default 0% NA tax. task-6264468 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The sales order screen is now easier to use on phones, with a cleaner product search drawer, compact action menus, and mobile-friendly order lines. Customers can configure combo products, discounts, shipping, coupons, and rewards more reliably from small screens, reducing friction for mobile sales workflows.
Original PR description
Mobile UX pass on the Sales quotation/order screen, including a fix for combo products being effectively unconfigurable on mobile: the product catalog search panel and the order line actions (combo…
Mobile UX pass on the Sales quotation/order screen, including a fix for combo products being
effectively unconfigurable on mobile: the product catalog search panel and the order line actions
(combo configurator, manual discount, shipping, loyalty coupon/reward) were designed desktop-first and
didn't adapt well to small screens.
Current behavior before PR:
- Configuring a combo product was not possible at all from mobile: tapping a combo line opened the
generic line form (product_id as a plain many2one_barcode field) instead of the combo configurator, so
there was no way to pick combo items on a small screen.
- The product catalog search panel used the generic responsive web.SearchPanel layout on mobile, which
is cramped and hard to use on a small screen.
- Order lines (mobile kanban) exposed raw inline controls ("Add Line", "Add Section", "Add Note",
"Catalog") directly in the list footer.
- Shipping / discount / coupon / reward were desktop-sized buttons with no mobile-specific layout,
competing for space on small screens.
Desired behavior after PR is merged:
- Tapping a combo line on mobile now opens the combo configurator dialog to pick items, same as the
desktop flow.
- The product catalog search panel opens as a dedicated mobile drawer (slide-in panel with backdrop)
instead of the generic responsive layout.
- Order lines mobile kanban drops the inline create controls in favor of a single "Add" button that
opens the product catalog.
- Combo selection and manual discount are exposed as compact dropdown widgets (combo_menu /
discount_menu) on mobile.
- Shipping / discount / coupon / reward actions are split into a compact mobile variant and the
existing desktop variant (d-none d-md-block).
- Combo lines can be deleted directly from the combo configurator dialog on mobile.
task-5270010
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThis update improves several everyday screens by making user lists easier to filter, invitations easier to understand, and password or two-factor authentication prompts clearer. It also cleans up small visual details and improves navigation after creating employees, helping administrators and users complete common tasks with less confusion.
Original PR description
This PR adds various UI improvements in different modules. # Base - 3 filters to group users by fields: company, language and role in company (user/admin) - 2 new optional fields in the user list…
This update rewrites the internal review instructions to make pull request reviews more consistent and accurate. It helps reviewers check the right version of the code, consider related enterprise changes, and verify affected areas before reporting issues.
Original PR description
Follow-up to #285015. Rewrites `skills/odoo-review/SKILL.md` after running 10 pr reviews with various models, with and without the skills and seeing what worked well and what didn't - The guidelines files often weren't read - The enterprise part of the PR was often ignored - A wrong / stale version of master was often used for the diff - Consumers of changed interfaces were not checked consistently This PR improves the reviewer behaviour in those regards
Settling large sales orders in Point of Sale is now faster and smoother. The change reduces repeated background calls and screen refreshes, improving cashier experience especially for orders with many lines or loyalty rewards.
Original PR description
In `settleSO`, two per-line bottlenecks were addressed: 1. `has_valued_move_ids` was called once per order line via a separate RPC, causing N sequential HTTP round-trips. It is now computed server-side inside `read_converted`, which is already called once for all lines. 2. `addLineToCurrentOrder` was awaited per line, yielding to the event loop each iteration and triggering a full Owl re-render for every line. Lines are now created directly, batching all mutations into a single render. `recomputeOrderData()` is called once after the loop. `updatePrograms` is moved to a `pos_sale_loyalty` patch on `settleSO` so the loyalty concern belongs to the bridge module. opw-6319922 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285822 Forward-Port-Of: odoo/odoo#271742
This update improves online shop search speed by adding the missing database support needed for product description filtering. Businesses with larger product catalogs should see search results load much faster, improving the customer shopping experience.
Original PR description
### Description: Following commit e9d435d1c865e1f462ce2e4bb2c0715ec97c8b10, some fields were missing proper indexes, causing the e-commerce search to be slow. This commit adds an indexes on `description_ecommerce` to optimize the filters of the query. ### Benchmark: | Nb of product | Before | After | |-----------------|----------|---------| | 747 | 6m 15s | 91 ms | ### Reference: opw-6513905 ___ I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287528 Forward-Port-Of: odoo/odoo#287381
Indonesian payroll rules now classify employee health insurance consistently and show company pension and old-age contributions in gross income while keeping take-home pay unchanged. This improves payslip transparency and aligns the related accounting entries with the updated payroll treatment.
Original PR description
Remove unused salary rule categories, reclassify BPJS Kesehatan (Employee) as an Allowance, and add a Gross Total rule alongside matching JHT/JP Company deduction rules so company contributions show in gross income without affecting net pay. Also configures the accounting entries for the reclassified BPJS Kesehatan rule. Upgrade PR: https://github.com/odoo/upgrade/pull/11169 task-6343536
The accounting dashboard onboarding has been refined to make tax return setup clearer and more relevant. Companies marked as not subject to VAT will no longer see unnecessary tax report and return options, reducing confusion during configuration.
Original PR description
This commit makes minor improvements in the account onboarding dashboard. - Adds helper for Tax Return kanban card and updates the action button string. - Hides some Tax settings if the company is "Not Subject to VAT" (check added in community)
Payroll warnings for Belgian payroll have been cleaned up and improved so HR teams can better understand and act on them. This helps reduce confusion during payroll processing and supports more reliable employee payroll administration.
Original PR description
Cleans and improves payroll warnings task: 6357419
Belgian payroll Dimona declarations can now be prepared for asynchronous batch submission while keeping the existing direct submission flow unchanged. The update also lets employees be saved when some Dimona-required information is missing, flags the issue for follow-up, and prevents duplicate or invalid follow-up declarations.
Original PR description
As part of a partnership with a social secretariat (*chut chut pas de marques*), some Odoo instances that use the Belgian payroll will submit their dimona declarations via the batch channel. This…
As part of a partnership with a social secretariat (*chut chut pas de marques*), some Odoo instances that use the Belgian payroll will submit their dimona declarations via the batch channel. This causes all sorts of problems with the current flow, which uses the ONSS web service and assumes everything happens right away. This PR aims to introduce several hooks/entry points for an async channel to be able to be 'added' on top of the standard belgian payroll without the need to massively rewrite parts of it. It also fixes 2 bugs discovered whilst working on this batch channel flow. Note that without specific code overrides (for which this PR introduces helper methods), the behaviour is nigh identical to what it was before: the REST flow still works as it did before. The only behavourial change introduced by design in commit `l10n_be_hr_payroll: don't abort a save over incomplete Dimona data`: instead of outright preventing a user (or a piece of code) from creating an employee with missing data (with regards to the dimona declaration), it saves it with a note in the chatter + the 'Dimona Issues' flag.
The Belgian payroll configuration now includes an updated value for the training time off threshold used in salary rule calculations. This helps keep payroll processing aligned with current requirements for Belgian HR payroll.
Original PR description
add new value to the training_time_off_threshold salary rule param. task-6545545 Forward-Port-Of: odoo/enterprise#131162 Forward-Port-Of: odoo/enterprise#131080
This update consolidates Spanish electronic invoicing settings and aligns the Canary Islands accounting plan with the main Spanish localization setup. Businesses using Spanish localization get a cleaner configuration experience and more consistent tax/account templates across mainland Spain and the Canary Islands.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Approved employee expenses are now automatically marked for reimbursement through payroll, removing the need for a separate “Add to Payslip” step. Payroll teams can still remove an expense from a payslip when needed, reducing manual work while keeping control over exceptions.
Original PR description
modules: documents_hr_expense, hr_expense_extract, hr_expense_stripe, hr_payroll_expense, l10n_be_hr_payroll_expense We have now to consider `approved` expenses when including them in an `hr.payslip` Remove the `Add to Payslip` action on `hr.expense`, the expense will now be flagged as `refund` in payslip at the approval step. It will still be possible to remove expenses from a payslip by pressing the `Remove from Payslip` button Community PR: https://github.com/odoo/odoo/pull/279468 Upgrade PR: https://github.com/odoo/upgrade/pull/10950 Task [link](https://www.odoo.com/odoo/project.task/6327097) task-6327097
Expense users now approve expenses instead of posting them, and approval creates draft accounting entries for accountants to review and post. This clarifies responsibilities between HR expense management and accounting, while adding easier access to expense-related journal entries and attachment import options.
Original PR description
modules: `hr_expense, sale_expense, project_sale_expense` Removing `accounting` functional flow from the `expense` module. - The `hr_expense` user used to `post` expenses, now they can only `approve`…
modules: `hr_expense, sale_expense, project_sale_expense`
Removing `accounting` functional flow from the `expense` module.
- The `hr_expense` user used to `post` expenses, now they can only `approve` them.
- Approving an expense will create `draft` moves.
- `accountant` users will post the moves instead.
- An `employee-paid` expense linked to a `draft` move will be considered as `approved`
- When the move gets `posted`, the expense will be set to `posted` too.
- A `company-paid` expense linked to a move, it will be considered `paid`, regardless of the `move.state`
- Removing the `hr.expense.post.wizard` for `employee-paid` expenses, the accounting date default is now `today`
- the `sale_expense` option to import attachments is now on the `sale.order` form view, as a button that opens a wizard to select what attachments the user wants to import from linked expenses
- `journal_id` on `hr.expense` is now computed, as we lost information for `employee-paid` expenses by removing the wizard
- Add a filter in the `account.move` list view to display entries linked to expense
- Add a link from journal dashboard to all the draft moves linked to expenses
Enterprise PR: https://github.com/odoo/enterprise/pull/126246
Upgrade PR: https://github.com/odoo/upgrade/pull/10950
Task [link](https://www.odoo.com/odoo/project.task/6327097)
task-6327097Manufacturing backorders created from already planned orders are now planned automatically, reducing manual follow-up for production teams. Time estimates and actual durations are also calculated based on remaining and produced quantities, making production planning more accurate.
Original PR description
1) auto plan backorders When a backorder is created from a planned manufacturing order, automatically plan it. 2) adapt duration/duration_expected's calculation Make duration_expected based on 'to produce' quantity (production's quantity minus quantity previously produced) Make duration based on produced quantity (if no time_ids) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Kanban views embedded inside forms now use tighter, more consistent spacing instead of keeping the standalone view layout. The “New” button in kanban views also gets a visual refresh, making the interface cleaner and easier to use.
Original PR description
A kanban inside a form kept the padding and the gap of the standalone view: the form neutralizes them through `--KanbanRecord-margin-*`, but ENT rewrites them, at the same specificity. We now set the specificity directly in COM so the contextual adaptation takes the priority. This commit also improves the design of `o-kanban-button-new` inside the kanban renderer. ENT: https://github.com/odoo/enterprise/pull/131135 task-6527607 | Before | After | |--------|--------| | <img width="1388" height="712" alt="Screenshot 2026-09-09 at 15 03 52" src="https://github.com/user-attachments/assets/cdfe4895-4cc4-45a7-b5ba-2c2f52204d99" /> | <img width="1383" height="677" alt="Screenshot 2026-09-09 at 15 03 12" src="https://github.com/user-attachments/assets/2b5048af-b8a4-49fe-9f45-94fde40cc2b5" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
When a backorder is created from an already planned manufacturing order, it is now planned automatically as well. This helps keep production scheduling consistent and reduces manual follow-up for manufacturing teams.
Original PR description
When a backorder is created from a planned manufacturing order, automatically plan it. task: 6456386
French companies using the normal fiscal regime are now directed to an ASPOne-hosted portal to submit their tax package. Companies on the simplified regime can choose between the existing Odoo submission flow and the ASPOne portal, with a guided setup shown when an ASPOne account is needed.
Original PR description
As part of the management of the "liasse fiscale" in France, we handled the submission of the simplified "liasse fiscale", which is directly integrated into Odoo. This commit makes that for companies with normal (as not simplified) fiscal regime, users are redirected to a white-label portal hosted by ASPOne. And it allows users from simplified fiscal regime companies to choose between both options. If there is no account for this db/company combo a wizard is displayed to get the needed info to create an account on ASPOne. Task: 6460125 Task: 6060727 IAP PR: https://github.com/odoo/iap-apps/pull/1887
Bank reconciliation now supports matching rules that can automatically pair and reconcile accounting entries, including configurable payment tolerance and rule order. This brings back useful behavior from the previous bank reconciliation experience and should reduce manual matching work for finance teams.
Original PR description
This commit introduce Matching rules, a new type of reco models to match and reconcile aml automatically, with possibility to add payment tolerance and a matching order. This kind of reco models was already there in the old bank rec widget. Linked:https://github.com/odoo/odoo/pull/287010 task-6425611
The generic Profit and Loss report no longer includes the "Net Profit Left After Allocations and Withdrawals" section. This keeps the report focused on core business income and expenses, without owner draws or profit allocation details.
Original PR description
This commits removes "Net Profit Left After Allocations and Withdrawals" section from the Profit & Loss generic report. This keeps the report clean and focused purely on business income and expenses by removing owner draws and profit allocations. task-6565605
Activities linked to bank transactions now take users directly to the relevant bank transaction instead of a less useful bank statement line. Users can also schedule one activity for multiple reconciliation records at once, saving time and reducing repetitive work.
Original PR description
When an activity is added to a bank transaction ( typically: upload document) the assignee is currently redirected to the bank statement line. It doesn't bring any value and doesn't allow him to do anything. Instead of that, we should lead him to the bank transaction. For the activities applied on the bank transaction, bank statement line is replaced by the said bank transaction. In addition, on the reconciliation view the user can now select multiple records and through a single form schedule an activity for all of them at once. task: 6010147
RATIONALE
In some cases (luxury, big corporate company) people want to be able to
review all messages generated by Odoo that are sent to the customers.
This is important when branding / copy writing is considered valuable
(e.g. "Your ticket has been closed" → "We are happy to announce that your
care ticket ...").
Currently we have several ways of generating them
* using a mail.template (used either as template.send_mail() in code, either
due to tracked changes, either with manual usage of templates);
* message_post → post a body, and if recipients to notify by email content
is encapsulated in an email layout
-> can be manual (chatter), message_type being email (incoming email) or
comment (user input in chatter)
-> can be automatic (calling message_post in code), generally with
message_type being notification, auto_comment
* message_post using rendered body based on a qweb view (in code), see
message_post_with_source
* mail.mail manual creation → code only (as only admins can create mail.mail)
* message composer
-> may be used to post a message, on a single record or in batch, based
on a template or using custom body
-> may generate mail.mail in batch (standard mailing usage)
* mass mailing → uses message composer to generate emails
It is currently not possible to review through interface all content that
might be sent to clients automatically: mail.templates can be found and
modified, but strings inlined in code cannot (only through code or
customization). Views can be found but there is no easy way to find them
in the UI.
SPECIFICATION: AUDIT LOG
At least give a way to know a mail.mail was created automatically / manually
* when a template is used, keep mail_template_id on message. Note that if
content was modified manually, template_id is still propagated;
* when it is generated through a mass mailing, keep mailing_id on mail.mail
* when it is generated automatically by message_post in code → message_type
is 'notification', which is ok
* when it is generated by users → message_type is 'comment', which is ok
* add a flag on qweb views used in posting process so that we can filter and
find them easily. Add a menu entry below "Email Templates" to find them
Task-6368610 [mail] Track content source
Part of Task-6260135 [mail] Ability to review outgoing contentThis PR adds various UI improvements in different modules. # Base - 3 filters to group users by fields: company, language and role in company (user/admin) - 2 new optional fields in the user list view: date of creation and default company - possibility to access an user form by clicking on the pending invitation badge - button to hide/show password in identity check form and password change form - improves the clarity of the password asked during identity check by stating that it requires the admin password # Base_setup - Removes the icon next to the number of active users in general settings # Auth_signup - Adds a filter grouping users by the state of the invitation sent - Changed the color of the "Invited" status from blue to grey, indicating the user is still a draft - Changed the message in the notification received when sending a mail invitation to a user to make it more clear # Auth_totp - Improves the readability of 2FA forms issued from mail 2FA and authenticator 2FA in order to reduce the mental load and make the form clearer and more explicit while also removing the "cancel" button in the forms. - Modifies the mail template containing the code by moving the expiration delay directly under the code. - Updates the tests by removing the verification of a deleted label and modify various string values # Web - Hides logo in webclient forms for companies having no logo or using the default logo # Hr - Makes the error message clearer when trying to create an employee for a company they don't belong to by indicating what to do to fix the issue. - Adds a redirection towards a user's newly created employee form when clicking on the "Create employee" button in the user form, allowing to check if the information are correct # Crm - Add the possibility to search on opportunity in pipeline and leads analysis views Task-6179091 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr