Saturday, September 12, 2026
85 changes · master
Security fixes and vulnerability patches
This change prevents full authentication tokens from being written to logs in the Peppol accounting integration. It reduces the risk of sensitive credential exposure while preserving useful logging for troubleshooting.
Original PR description
don't log full token Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287738 Forward-Port-Of: odoo/odoo#287262
Discuss now creates a separate secure key for each call channel instead of relying on a shared secret alone. This reduces the risk of one channel's call access affecting another and helps keep real-time conversations better isolated.
Original PR description
derive channel-specific key from db secret and the channel id. Forward-Port-Of: odoo/odoo#287778 Forward-Port-Of: odoo/odoo#286304
New functionality added to Odoo
Accounting users can now define matching rules that automatically pair and reconcile bank statement lines with accounting entries. The rules support payment tolerance and ordering, helping reduce manual reconciliation work and restore capabilities from the previous bank reconciliation experience.
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/enterprise/pull/130703 task-6425611
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
Resolved issues and error corrections
The attendance Gantt test setup now limits its data to the company created for the test. This prevents unrelated demo company records from affecting results, making quality checks more stable without changing business features.
Original PR description
Some tests in `hr_attendance_gantt` could include employees from other companies, making their expected employee counts depend on unrelated demo data. This commit adds the test company to the common domain so the gantt data only includes employees created for the test case. [error-945955](https://runbot.odoo.com/odoo/error/945955) Forward-Port-Of: odoo/enterprise#128108
Code cleanup and technical improvements
This internal cleanup changes several mail and live chat values so they are calculated only when needed instead of stored separately. This reduces unnecessary data updates and helps keep messaging behavior simpler and more reliable without changing what users see.
Original PR description
Before this commit, a value like isVideoStreaming or offlineMembers is a field with a compute. Nothing else writes it, so the field only stores what the compute makes. This commit declares each of them as a computed instead, made on read. A member list writes nothing when it sorts now, so its FIXME goes. https://github.com/odoo/enterprise/pull/131284
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…
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 contentEmployee-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 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
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
The invoice form now hides Ecuador reimbursement details from users who do not have accounting access. This prevents access errors when non-accounting users open invoices, improving reliability without changing accounting workflows.
Original PR description
The reimbursement lines are added to the invoice form without any group restriction, while their model can only be accessed by accounting users. As a result, opening an invoice form as a user without accounting rights can raise an AccessError when the form view tries to retrieve the reimbursement subview. This commit restricts the reimbursement page to the groups allowed to access reimbursement lines. [error-946579](https://runbot.odoo.com/odoo/error/946579) Forward-Port-Of: odoo/enterprise#129981
Card payments no longer fail when a previous expense created from the same card is missing a date. Undated expenses are now only included in all-time checks, helping employees continue using their cards while keeping spending limits accurate.
Original PR description
Fix a traceback preventing card users to make any payment with their card if at least one expense created by said card has no date Steps to reproduce: - Install hr_expense_stripe_demo (to access the test wizards) - Setup the stripe (demo) account with a valid card and funds - Create one transaction with the card - Remove the date of the generated expense -> Any further transaction with that card will fail After this commit: An expense with no date is considered only in the 'all time' Ticket [link](https://www.odoo.com/odoo/project.task/6326124) opw-6326124 Forward-Port-Of: odoo/enterprise#130337
Website forms now ignore fields without a name when saving page settings. This prevents confusing repeated error popups caused by invalid form markup while keeping normal form saves working as expected.
Original PR description
On save, the form option collects the `name` of every non-custom form input on the page and sends the list to `formbuilder_whitelist`. An input with an empty name (hand-edited or generated markup) yields '', which the server rejects with a ValueError since it matches no field of the model. As the whitelist RPC is fired without being awaited, the save itself succeeds and the broken field persists in the page, so every subsequent save of that page then raises the same unexplained RPC error dialog, forever. Skip nameless inputs: a field that doesn't post anything has nothing to whitelist. task-6251785
The Contracts page under Employee Records no longer offers a Kanban view option that was not actually available. This prevents users from selecting a view that would not work and keeps the page choices clearer.
Original PR description
We don't have a Kanban view for contracts, but we still allow users to select that view type. After discussion with the team, we've deemed that view unnecessary. Instead of implementing the Kanban view, we'll just remove that option from the "Employee Records" (Contracts) page. opw-6475797 Forward-Port-Of: odoo/odoo#284829
German point-of-sale sessions using Fiskaly can now close successfully when an order customer is an address contact without its own name. The system uses the displayed contact name as a fallback for required compliance export data, preventing session-closing crashes.
Original PR description
Steps to reproduce: - German PoS with Fiskaly TSS configured - Set a customer that is an address contact (type invoice/delivery/other) on an order; such a contact has no name of its own, it is…
Steps to reproduce: - German PoS with Fiskaly TSS configured - Set a customer that is an address contact (type invoice/delivery/other) on an order; such a contact has no name of its own, it is displayed with its parent's - Close the session Issue: Closing crashes with "TypeError: 'bool' object is not subscriptable" and the session cannot be closed at all. Cause: _get_dsfinvk_cash_point_closing_data builds the DSFinV-K buyer block from partner.name, which is only guarded by "if partner := o.partner_id". res.partner.name is not required: the res_partner_check_name constraint only enforces it for type='contact', so an address contact stores NULL there and partner.name reads as False, which cannot be sliced. Fix: Fall back on complete_name - what the UI displays for those contacts, "Parent Company, Delivery" - and on a literal when even that is empty, since the buyer name is mandatory in the export. Reading name first leaves the exported value untouched for every partner that has one. opw-6518336 Forward-Port-Of: odoo/enterprise#131212 Forward-Port-Of: odoo/enterprise#129709
Odoo now processes official Flow 10 response messages for French PDP reporting instead of only storing them as files. Rejected reports are marked correctly, users can see the rejection details, and corrected reports can be resent with a new transmission reference.
Original PR description
Flow 10 PPF responses were stored as attachments without being processed. Consequently, rejected reports remained marked as sent, the rejection reason was not shown to users, and corrected reports could not be submitted again. Process the PPF response codes, update the flow state, and log the returned details in the chatter. Keep response attachments separate from the outgoing payload and allow rejected reports to be manually resent with their original moves and a new transmission identifier. no task id Forward-Port-Of: odoo/odoo#287737 Forward-Port-Of: odoo/odoo#287338
The Timesheets Assistant sample data generator now selects regular project tasks instead of template tasks. This ensures generated sample activities can be linked to tasks correctly, making demo or onboarding data more useful and accurate.
Original PR description
The Timesheets Assistant sample data generator searches project.task with `is_template != False`, so it collects template tasks instead of regular ones and the generated activity never links to a task. Task-6566451 Forward-Port-Of: odoo/enterprise#131248
Updated the point of sale and stock-related test coverage so product loading limits are checked consistently when stock features are installed. This reduces false test failures and helps keep checkout product loading behavior reliable across module combinations.
Original PR description
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching…
## Context: When all references to stock functionality were extracted from point_of_sale in this PR: #241368, we decoupled the query ordering logic from the rest of our product.template data-fetching code: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L190 This allowed us to completely override (not extend) the ordering of the loaded products in our new pos_stock module: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/pos_stock/models/product_template.py#L42-L65 Notice the difference in point_of_sale: https://github.com/odoo/odoo/blob/1170bafbd7d9461d13ba1d6020d6f8487660763c/addons/point_of_sale/models/product_template.py#L403-L416 This was causing problems with our existing test for this feature in point_of_sale because we were explicitly examining the ordering of the products; obviously this ordering would be different when pos_stock is installed alongside point_of_sale. Thus, we must decouple our original test for this feature so that ordering can be examined independently in each module's tests. ## Now: We have one test in point_of_sale that just makes sure our limited products loading feature actually caps the number of products loaded. This test will work correctly whether or not pos_stock is installed. In addition, we have one more test in point_of_sale and pos_stock that explicitly examines the ordering of the products in these limiting conditions when both modules are installed. The point_of_sale test will be skipped when pos_stock is installed because the latter module defines conflicting ordering. runbot-243064 Forward-Port-Of: odoo/odoo#283621
This fix prevents scheduled Chilean electronic invoicing status checks from failing when the tax authority returns an empty response. It helps keep automated invoice processing running reliably without manual intervention.
Original PR description
When checking the status of a DTE, sometimes the response will have no `text`. This causes a traceback error that halts execution of the cron `cron_run_sii_workflow`. opw-6322106 Forward-Port-Of: odoo/enterprise#130873 Forward-Port-Of: odoo/enterprise#129582
This fixes SEPA credit transfer export files so they no longer include an address field that some European banks reject. Businesses using Austrian, German, or similarly strict banks should be able to submit batch payment files successfully again.
Original PR description
### Issue before this commit: Generating a SEPA Credit Transfer XML for certain European banks (e.g., Austrian and German banks) fails because the generated XML contains an unexpected `<CtrySubDvsn>`…
### Issue before this commit: Generating a SEPA Credit Transfer XML for certain European banks (e.g., Austrian and German banks) fails because the generated XML contains an unexpected `<CtrySubDvsn>` tag inside the `<PstlAdr>` node, leading to the rejection of the batch payment file. ### Steps to reproduce the issue: 1. Download Accounting and l10n_at 2. Go to settings and activate SEPA Credit Transfer / ISO20022 3. Go to Journals > Bank > set an account number 4. Create an austrian contact (ex. FK Austria Wien AG) and set in the invoicing tab a bank (ex. AT526000071856851733) and set it trusted 5. Go to Bills, create a new one with the contact created and confirm it 6. Then click 'PAY' and select SEPA Credit Transfer 7. Go to Vendors > Batch Payments 8. Create a new one with: 1. Bank as bank 2. SEPA Credit Transfer as Payment Method 3. Add the bill just created 9. Validate and download the XML 10. See that a wrong tag <CtrySubDvsn> is added. This makes some banks refuse it ### Cause of the issue: External commit 30b023d394a5e4de64873188aa1d5961fecccb10 introduced the `<CtrySubDvsn>` tag to support US and CA requirements. However, the change was incorrectly applied to the common `account_iso20022` file, making it leak into standard European SEPA exports where the tag is not compliant with certain strict banking validation rules. ### Reason to introduce the fix: Revert the generic addition of the `<CtrySubDvsn>` tag in the common ISO20022 XML generation and restrict it only to the specific localizations (US/CA) that require it. This brings the `<PstlAdr>` node back to compliance, allowing Austrian, German, and other European banks to successfully process the files. opw-6523035 Forward-Port-Of: odoo/enterprise#131156 Forward-Port-Of: odoo/enterprise#131090
Image fields now apply an Android camera compatibility workaround only for Chromium-based Android browsers that need it. This prevents other browsers and the Odoo mobile app from showing unnecessary or confusing file picker options while preserving camera access where it was missing.
Original PR description
Since Android 14, Chromium sends a file input accepting only images straight to the photo picker, which has no "Camera" entry. The image fields work around it by appending `dummy/allowAndroidCamera`…
Since Android 14, Chromium sends a file input accepting only images straight to the photo picker, which has no "Camera" entry. The image fields work around it by appending `dummy/allowAndroidCamera` to their accept attribute: a mimetype which is not an image is enough to get the generic chooser, and its camera, back. https://issues.chromium.org/issues/40937303 That invalid mimetype was appended for everyone, while only the browsers based on Chromium on Android need it: - the issue is an Android one, the desktop file dialogs are not concerned - the native app builds its own file chooser out of the accept attribute, and the invalid mimetype makes it offer the document picker on a field which only accepts images - Firefox and Safari are not based on Chromium and are not affected The workaround is now limited to the browsers needing it, and the expression moved from the template to a getter, since it is no longer a simple concatenation. Code made by Claude Supervised by RFR --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287923 Forward-Port-Of: odoo/odoo#285643
Payslips now only include public holidays for the employee version's own company, even when multiple companies are selected. This prevents holidays from one country or company appearing incorrectly in another company's payroll calculations.
Original PR description
Issue: - Create a public holiday in France, and generate a payslip in Belgium, with both companies selected. - French public holidays will appear in the belgian worked day lines. Fix: replace `self.env.companies.ids` -which returns all selected companies- in `_get_leave_domain` with `self.company_id.ids` to match the company of the current version in the payslip. task-id: 6425963 Forward-Port-Of: odoo/odoo#287638
Fixed an issue where saving a message after opening edit mode could incorrectly mark it as edited, even when no content was changed. This keeps chatter message history more accurate and avoids confusion for users reviewing communication records.
Original PR description
Steps to reproduce: ------------------------------------- 1. Open the chatter of any record 2. Open the full composer for the Log Note 3. Add some text and paste some images > Post the log note 4.…
Steps to reproduce: ------------------------------------- 1. Open the chatter of any record 2. Open the full composer for the Log Note 3. Add some text and paste some images > Post the log note 4. Click on the Edit option 5. Save the message without editing anything Observation: ------------------------------------- You will notice that the (edited) label appears even though the message wasn't edited at all, only the edit mode was made active. Issue: ------------------------------------- When a message is posted via the mail composer, the email conversion pipeline injects MSO conditional comments like `<!--<![endif]-->` and `<!--[if mso]>...<![endif]-->` into the HTML body. These comments are added by the `_hideForOutlook` and `createMso` https://github.com/odoo/odoo/blob/083e091eaa7d983f6c826c02b0d0652a821227fb/addons/mail/static/src/views/web/fields/html_mail_field/convert_inline.js#L1978-L1988 https://github.com/odoo/odoo/blob/083e091eaa7d983f6c826c02b0d0652a821227fb/addons/mail/static/src/views/web/fields/html_mail_field/convert_inline.js#L1699-L1707 functions to ensure Outlook compatibility, they wrap responsive elements so that Outlook receives simplified table-based fallbacks while modern clients see the original layout. The stored message body on the server retains these comments. When a user clicks "Edit" on such a message, the body is loaded into the OdooEditor. The browser's DOM parser treats `<!--<![endif]-->` as standard HTML comment nodes, which are not preserved in `innerHTML` serialization. So the editor returns the body without these comments, even if the user made no changes. The `edit()` method in then compares `updatedBodyEl.innerHTML` (from editor, no comments) against `messageBodyEl.innerHTML` (from server, has comments), finds a difference, and sends a update to the backend, which stamps the message with the (edited) label. Solution: ------------------------------------- Before comparing innerHTML, strip all HTML comment nodes from both the original and updated body elements. This is done on throwaway DOM elements created solely for comparison. The actual body sent to the server (`body` parameter) is never modified. Note: ------------------------------------- An alternative approach would be to strip comments at the string level using a regex (`html.replace(/<!--[\s\S]*?-->/g, '')`) before creating the DOM elements. This is valid since HTML comment syntax `(<!--...-->)` is strictly defined and no nesting is allowed, so the regex is reliable. This commit also preserve images while trimming empty message boundaries. Newer test covers this issue. opw-6328529 Forward-Port-Of: odoo/odoo#287502 Forward-Port-Of: odoo/odoo#274927
User role changes now correctly update the related access groups, even when the role is not tied to a specific functional access. This prevents mismatches between what administrators see in the user form and the permissions actually applied after saving or reloading.
Original PR description
It is a functional request to add him to the groups even if he is not involved by a functional access. [FIX] base: prevent group desync in user onchange When editing a user in the web client, the…
It is a functional request to add him to the groups even if he is not involved by a functional access. [FIX] base: prevent group desync in user onchange When editing a user in the web client, the onchange mechanism creates a virtual record using `new(values, origin=record)` to build the baseline snapshot used for field diff tracking. In `res.users.new()`, logic automatically adjusts `group_ids` (adding or removing `base.group_multi_company` depending on the number of companies on the user) as a side effect. When `new()` was called with an `origin`, this side effect corrupted the reference snapshot. Consequently, the onchange return value failed to detect or report the real delta to the web client, leaving the UI in an incorrect or desynchronized state (e.g. `role` radio buttons or access right checkboxes out of sync with actual groups). Fix this by skipping the automatic group adjustment in `new()` when `origin` is present, keeping the reference snapshot clean. Add tour tests to ensure `role` and group checkboxes stay synchronized across saves and page reloads in the web client.
This fixes a display issue where mega menu content could touch the edge of the mobile website preview. Mobile menus now keep the expected spacing, making navigation look cleaner and easier to read.
Original PR description
Steps to reproduce: - Open a website in mobile preview. - Add a mega menu and select the "Odoo Menu" template. - Open the mega menu. => Its content touches the left edge of the mobile panel. Before this commit, the mega menu rework [1] removed the horizontal padding override required by nested `.container` elements. After this commit, mega menu containers keep the expected grid gutter on mobile. [1]: https://github.com/odoo/odoo/commit/ff5423bc3aa75e47b210ce98f3efba8c75459a5a
Website theme previews now adjust text and icon colors when users choose darker color palettes. This prevents hard-to-read elements in the configurator, making theme selection clearer and more reliable.
Original PR description
Steps to reproduce: - Open the website configurator. - Select a dark color palette. - Preview the "Eclipse" theme. => The shaped icons in the Features section are hard to see. Before this commit, static theme previews kept the text colors compiled for their original palette when `bg-o-color-X` backgrounds changed. This could result in dark text on a dark background. After this commit, configurator previews recompute the text color for each palette background and keep shaped icons readable. task-6485048
This change fixes how the mail app tracks whether a conversation is currently in focus when it is open in more than one view. It prevents one view losing focus from incorrectly marking the whole conversation as unfocused while another view is still active.
Original PR description
Before this commit, the Thread component writes isFocusedByThread on the record it displays and the record turns that flag into isFocusedCounter. The problem is that two views of the same thread share the one flag, so the first to lose the focus clears it while the other still has it. This commit keeps the focus in the component and lets each view hold its own share of the counter, so a thread is focused as long as one of its views is.
The quotation document form now clearly shows that an attachment must be selected before saving. This prevents confusion when creating quote documents by highlighting the required step directly on the attachment field.
Original PR description
When trying to save an empty quotation document from the form view, the save is blocked because the `name` field is required. However, `name` is readonly when no attachment has been selected. As a result, the form doesn't display the required-field decoration on that field, which is confusing. The attachment field should be marked as required in the view instead. This makes it clear that an attachment must be selected first, after which the `name` field becomes available and can be filled in. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287400
Fixed an issue where reusing the calendar multi-create popover could incorrectly limit available Time Type options after creating and deleting working-time entries. Users can now continue adding schedule entries without needing to refresh the page to restore the full list of allowed choices.
Original PR description
Issue: The calendar multi-create popover retains its form values so they can be reused when adding entries to another selection. In a variable working schedule, this retained state incorrectly…
Issue: The calendar multi-create popover retains its form values so they can be reused when adding entries to another selection. In a variable working schedule, this retained state incorrectly restricted Time Type to the first allowed value after mass creating entries and deleting one occurrence. Refreshing the page restored all Time Type options because the form was then rebuilt from the complete backend value of `allowed_work_entry_type_ids`. Steps to reproduce: - Open a working schedule and switch it from Fixed to Variable. - Select multiple days and mass add working-time entries. - Select one of the created days and delete its entry. - Select that day again and open the Add popover. - Open Time Type and observe that only the first allowed type is available. - Refresh the page and observe that all allowed types are available again. Cause: `work_entry_type_id` is filtered by the computed `allowed_work_entry_type_ids` relation. The relational model keeps every relation ID in `StaticList.currentIds`, but only materializes the loaded page in `StaticList.records`. Since this invisible domain dependency has no related display fields, its loaded page is limited to one record. When the multi-create popover was submitted or closed, https://github.com/odoo-dev/odoo/blob/23266b3a3bf0856dc147e3780e5ac54469bbcc53/addons/web/static/src/views/view_components/multi_selection_buttons.js#L169-L180 serialized x2many values from `StaticList.records`. This reduced `allowed_work_entry_type_ids` to its first loaded ID in the retained `multiCreateValues`. Reopening the popover reused that incomplete relation, so the Time Type domain correctly evaluated against only one ID. Solution: Serialize x2many values from `StaticList.currentIds` so every related ID is preserved. For loaded records, merge the cached record data to retain edited or display values, for unloaded records, retain an ID-only value. This keeps the complete domain dependency across calendar multi-create popovers without changing the backend Time Type computation. opw-6398706 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#280391
Employee availability is now shown consistently across Time Off and Attendance, including days outside contracts and flexible schedules. This prevents misleading calendar views by greying out unavailable periods and improves reliability for workforce planning.
Original PR description
purpose: 1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out of contract days,…
purpose:
1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out of contract days, flexible and fully flexibe employees. 2- In time off calendar view, if the employee does not have a contract at all, the current working schedule will appear in the calendar and it will not be greyed out. This is inconsistent with the behavior of the attendance application.
Fix:
1:
- implemented `_get_employee_unavailable_intervals` in employee model to be used in both time off and attendance.
- more optimized than the old implementation in time off as it calls `_work_intervals_batch` once per calendar instead of calling it for each contract in `_unavailable_intervals_batch`
- greys out "out of contract" periods
- for flexible and fully flexible employees, the whole period is considered available except leave periods
- for duration based calendars, morning and afternoon map to 12 hours of availability and full day maps to 24 hours of availability
- made `_get_calendar_periods` use version date start instead of contract date start and corrected a bug in tz conversion 2:
- made `_get_unusual_days` return True for all the days outside of contracts for the employee instead of not returning anything for them or getting values from the working schedule of the employee (means that they will be greyed out in the callendar view) and added a test for it
task-id: 5473055
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287019
Forward-Port-Of: odoo/odoo#258604This fixes a problem where the HTML editor could stay stuck with outdated content after a newer save happened elsewhere. The editor now uses the latest version stored on the record, helping users see the correct server-saved document and avoid stale edits.
Original PR description
Before this commit, an editor recovering from a stale document could stop on this error and keep the stale content:
```
Error: Concurency detected while recovering from a stale document. The
last history id of the server is different from the history id received
by the html_field_write event.
at CollaborationOdooPlugin.resetFromServerAndResyncWithPeers
```
This happens because the recovery compares the history id of the record with the one the html_field_write event carried. A write keeps only the last step id in the field, so an event handled after a later write names an id the record no longer holds. As a result, the recovery stops there and the document stays stale.
This commit fixes the issue by taking the history id read from the record as the new server reference, so the editor converges on the document the server holds.
https://runbot.odoo.com/odoo/error/944595
Forward-Port-Of: odoo/odoo#287523
Forward-Port-Of: odoo/odoo#287408This fix ensures automatic period-change entries are properly balanced and reconciled. It prevents leftover accounting lines from cluttering records and helps keep financial data accurate.
Original PR description
The previous code wasn't reconciling the destination and accrual moves, leaving potentially non-neutral journal items and their counterpart polluting the DB. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287524 Forward-Port-Of: odoo/odoo#279766
The certificate setup screen no longer shows an error banner simply because no password was entered for a key file. Users will only see the warning when they provided a password and it is incorrect, reducing confusion during certificate configuration.
Original PR description
When adding a key file without entering a password, an error banner is immediately displayed, incorrectly suggesting that the password may be invalid. Only show the error banner when a password was provided and is incorrect. Also refactored the compute function to avoid repeated try-except blocks. task-6299175 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286307 Forward-Port-Of: odoo/odoo#283589
This update corrects a small configuration screen issue in Belgian payroll settings caused by improperly closed fields. It helps ensure the settings page loads and displays as intended for users managing payroll configuration.
Original PR description
Found some fields that has closed bracket too soon in payroll_config_settings_views.xml. This PR expected to remove too son '/>' closures. task-6522569
Payslip summary cards now keep wage and worked-days values inside their borders on smaller screens or when amounts are long. This improves readability and avoids broken layouts for payroll users reviewing payslips.
Original PR description
The worked days/wage stat cards on the payslip form used flex-basis-*/bg-100 utility classes but no min-width guard, so the monetary fields (basic_wage, net_wage, sum_worked_days) could overflow past the card's border on narrower screens or with large amounts. Add min-w-0 on the cards so they can shrink within their flex row, and text-break on the big-number fields so long values wrap inside the card instead of spilling out of it. Forward-Port-Of: odoo/enterprise#131031
This fix stops the system from creating exchange difference entries when users reconcile journal items on accounts where reconciliation is not allowed. It ensures accounting records stay cleaner and avoids unexpected extra entries in this specific workflow.
Original PR description
Repro steps: 1) Create two misc entries with different foreign currency amount and different company currency amounts, on an account with "Allow Reconciliation" disabled (one debit, one credit). 2) Go to Journal Items, select both lines and click Reconcile. Issue: An exchange difference entry is generated. Fix: Move the control of the exchange difference moves creation to the account.reconcile.wizard instead of controling it inside action_reconcile of account.move Related PRs: https://github.com/odoo/enterprise/pull/130541 https://github.com/odoo/enterprise/pull/108362 Forward-Port-Of: odoo/enterprise#131145
Employee availability is now shown consistently across Attendance and Time Off planning views. Days outside an employee contract are clearly greyed out, while flexible schedules and leave periods are handled more accurately, helping managers plan with fewer misleading calendar gaps.
Original PR description
purpose: 1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out of contract days,…
purpose:
1- We should have a consistent way to compute `_gantt_unavailability` of employees in time off and attendance. Currently, some cases have inconsistent behavior such as out of contract days, flexible and fully flexibe employees. 2- In time off calendar view, if the employee does not have a contract at all, the current working schedule will appear in the calendar and it will not be greyed out. This is inconsistent with the behavior of the attendance application.
Fix:
1:
- implemented `_get_employee_unavailable_intervals` in employee model to be used in both time off and attendance.
- more optimized than the old implementation in time off as it calls `_work_intervals_batch` once per calendar instead of calling it for each contract in `_unavailable_intervals_batch`
- greys out "out of contract" periods
- for flexible and fully flexible employees, the whole period is considered available except leave periods
- for duration based calendars, morning and afternoon map to 12 hours of availability and full day maps to 24 hours of availability
- made `_get_calendar_periods` use version date start instead of contract date start and corrected a bug in tz conversion 2:
- made `_get_unusual_days` return True for all the days outside of contracts for the employee instead of not returning anything for them or getting values from the working schedule of the employee (means that they will be greyed out in the callendar view) and added a test for it
task-id: 5473055
Forward-Port-Of: odoo/enterprise#130714
Forward-Port-Of: odoo/enterprise#113498This fix prevents Saudi electronic invoices from being reset to draft while they are being submitted to ZATCA. It helps avoid accidental duplicate submissions in production, reducing the risk of taxpayer compliance issues while still allowing test workflows in sandbox and simulation modes.
Original PR description
Bulk sending is queued: the batch wizard stamps sending_data on the moves and lets the send cron do the work. Before this commit: Reset to Draft stayed available while the moves were being sent, so…
Bulk sending is queued: the batch wizard stamps sending_data on the moves and lets the send cron do the work. Before this commit: Reset to Draft stayed available while the moves were being sent, so the user could reset an invoice mid-submission. The invoice then ended up draft with an accepted submission and could be sent to ZATCA a second time, which ZATCA treats as a taxpayer compliance issue. After this commit: The records are locked on both sides, the way l10n_jo_edi does. Reading the state instead would not help, as a transaction only sees the snapshot taken when it started, in which the move is still posted. 1. When submitting, the moves that cannot be locked are skipped, as another transaction is already working on them. 2. When resetting to draft, the reset is refused if the records cannot be locked, otherwise it applies once the submission it races with committed. Reset to Draft stays available for invoices accepted in Sandbox and Simulation, as deleting or resubmitting test invoices is the point of those modes. Production remains covered by the l10n_sa_edi_is_production check. Steps to reproduce: 1. Install l10n_sa_edi and onboard a sales journal in Sandbox mode. 2. Create and post two invoices. 3. Select them, Action > Send & Print. 4. Select them again, Action > Reset to Draft. task-6267293 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284107
Colombian child contacts linked to a company with a NIT are no longer incorrectly treated as separate companies. This restores the expected company-and-contact display and makes those contacts show up when users search by the parent company name.
Original PR description
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company…
Issue: Colombian child contacts linked to a NIT company are displayed with their standalone name instead of "Company, Contact". Searching Contacts by the company name consequently returns the company but not its child contacts. Steps to reproduce: - Create a Colombian company with NIT - Add a child contact or address to that company - Filter Contacts by the company name - Observe that the child is displayed separately and is not returned Cause: The Colombian `is_company` computation classifies every partner with a Colombian NIT and qualifying obligations as a company: https://github.com/odoo/enterprise/blob/911686a31d5d3c1539d0dff7d16edf1ce9b101ca/l10n_co_edi/models/res_partner.py#L43-L53 Those fiscal values are commercial fields and are propagated to child contacts. Without checking that the partner is its own commercial entity, children are therefore classified as companies, preventing the standard display name logic from prefixing their parent name. Solution: We need to restrict the Colombian company classification to partners that are their own commercial partner. This preserves the NIT and obligation rules for actual companies while keeping their inherited child records as contacts, restoring both the combined display name and parent name search behavior. opw-6470958 Forward-Port-Of: odoo/enterprise#130373 Forward-Port-Of: odoo/enterprise#128986
This update fixes a failing automated test in the Expense Stripe module after related platform changes. It helps keep quality checks reliable so future updates can be delivered with confidence.
Original PR description
After the changes made in the community PR, a test failed. task-6299175
This fixes internal typing issues in the web and messaging code so translation text and date/time values are handled more consistently. The change helps developers catch mistakes earlier, reducing the risk of small translation or scheduling-related defects reaching users.
Original PR description
See individual commits for details.
This fixes an issue where some product variant images could be treated as general product images during installation or upgrades. Online stores will show and organize variant-specific images more accurately, reducing confusion for shoppers and staff.
Original PR description
Issue: when installing or upgrading `website_sale` (version 20.0), some variant images were incorrectly interpreted as template images. Fix: before interpreting an image as a template image, check whether it's used in one or more variants, and if so, interpret the image as a variant image instead (and assign in to the union of the variants' PTAVs). This PR also fixes a few cosmetic issues.
Opening or refreshing a live chat avatar now avoids changing the underlying chat member history. This prevents unnecessary system notifications and helps keep live chat behavior stable for users.
Original PR description
Before this commit, the avatar of a livechat is picked by sorting livechat_channel_member_history_ids, which sorts the relation itself: a read of the avatar reorders the records stored on the channel and notifies everything that reads them. This commit sorts a copy.
Live chat conversations with public visitors now show the visitor conversation avatar in the Discuss header instead of a generic thread icon. This makes live chat threads easier to recognize and improves consistency in the customer support interface.
Original PR description
Before this commit, the Discuss content header showed the thread icon instead of the avatar for a livechat held with a public visitor. This was because `showThreadAvatar` relied on `hasCorrespondentAvatar`, i.e. on a correspondent with an uploaded photo to display. A public visitor is a guest with no uploaded image, so it was false. The header now shows the avatar of any thread backed by a channel. Related Enterprise PR: https://github.com/odoo/enterprise/pull/130678 Task-[6526300](https://www.odoo.com/odoo/project/1519/tasks/6526300) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Live chat conversations with public visitors now show the visitor conversation avatar in the Discuss header instead of a generic thread icon. This makes WhatsApp-related chat views clearer and more consistent for support teams handling visitor conversations.
Original PR description
Before this commit, the Discuss content header showed the thread icon instead of the avatar for a livechat held with a public visitor. This was because `showThreadAvatar` relied on `hasCorrespondentAvatar`, i.e. on a correspondent with an uploaded photo to display. A public visitor is a guest with no uploaded image, so it was false. The header now shows the avatar of any thread backed by a channel. Related Community PR: https://github.com/odoo/odoo/pull/286960 Task-[6526300](https://www.odoo.com/odoo/project/1519/tasks/6526300)
The mail notification popover now reads notification information directly instead of going through an internal proxy. This is a small internal cleanup that simplifies the code and reduces maintenance risk without changing user-facing behavior.
Original PR description
Before this commit, the notification popover reads isFollowerNotification through _proxy. A relation gives the proxy of each record, so notification._proxy is the notification. This commit reads the field from the notification. Nothing outside the model reads _proxy any more.
This update simplifies how the Mail app defines certain internal default values. It does not change user-facing behavior, but helps keep the code easier to maintain and less prone to future mistakes.
Original PR description
Before this commit, suggestedRecipients wraps its default array in fields.Attr, and _resolve declares no value at all. This commit declares both with the value alone. https://github.com/odoo/enterprise/pull/131312
Marketing Automation has been redesigned to make campaign creation easier for non-technical users, with a visual workflow editor, clearer activity types, drag-and-drop organization, and more ways to enroll participants. The update also adds AI-assisted campaign creation so users can describe a campaign in plain language and get help building it.
Original PR description
As Odoo grows, we're always looking for ways to make our apps even more accessible and user-friendly. Over time, we've noticed that our current Marketing Automation app requires a bit of a technical…
As Odoo grows, we're always looking for ways to make our apps even more accessible and user-friendly. Over time, we've noticed that our current Marketing Automation app requires a bit of a technical background to get the most out of it. While the engine under the hood is super powerful, the sheer number of options can feel a bit overwhelming for everyday users who just want to get a campaign running quickly. To bridge this gap and open up the app to everyone, we're giving it a fresh, modern makeover! The goal of this task is to shift toward a fully visual experience. This PR introduces a brand-new custom graph view that makes campaign building much more intuitive. Instead of managing complex configurations through standard forms, users can now see their entire marketing flow mapped out clearly. Building a campaign becomes super straightforward: you can add, remove nodes on the fly to design your workflow visually. Instead of throwing all options into a single, heavy form, we've split the configuration into specific, easy-to-understand node types (like Delay, Filter, and Interaction). This keeps the interface clean, clutter-free, and way easier to use. ENT: https://github.com/odoo/odoo/pull/258112 Task-3866422
This update simplifies internal field definitions across several Odoo Enterprise apps and fixes an issue where social conversations waiting for an operator were not visible in the Livechat tab. Business users benefit from more reliable livechat handling, while the broader cleanup reduces technical complexity without changing day-to-day workflows.
Original PR description
Before this commit, these models wrap the default value of a field in fields.Attr. This commit declares those fields with the value alone, which leaves no fields.Attr in enterprise. Counterpart of "[REF] mail: declare a plain value without fields.Attr". https://github.com/odoo/odoo/pull/287950
This update streamlines how WhatsApp discussion information is managed behind the scenes. It removes an unnecessary internal field, helping keep the codebase cleaner and easier to maintain without changing the user experience.
Original PR description
Enterprise counterpart of "[REF] mail: drop the compute-only fields for computeds", which explains the why. https://github.com/odoo/odoo/pull/287867