Saturday, September 12, 2026
40 changes · master
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
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
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
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
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 contentSubscription-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
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
This 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
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
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.
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
Manufacturing 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
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
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
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
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
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
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.
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
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#113498Colombian 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 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.