Wednesday, September 9, 2026
155 changes · master
Security fixes and vulnerability patches
Live chat visitor routes now use a dedicated guest access check instead of relying on each route to apply it manually. This reduces the risk of accidentally exposing live chat actions while preserving the expected visitor experience.
Original PR description
Before this commit, all 25 CORS routes of the live chat are declared auth="public" and call force_guest_env() as their first statement, to replace the request user by the public one and put the guest matching the guest_token parameter in the context. The problem is that auth="public" is wrong for these routes, so a route that forgets to call force_guest_env() is left public. This commit turns the helper into two ir.http auth methods, force_guest and force_guest_optional, the latter for the routes a visitor reaches before having a guest, so a route is safe by definition. The website tracking route keeps its own lookup, as it must not drop the session of a logged in visitor. Note that authentication runs before the dispatcher parses the parameters, so the token is read from the json body or from the http parameters, depending on the type of the route. task-6259734 https://github.com/odoo/enterprise/pull/118774
New functionality added to Odoo
Time off balances can now be tracked separately in both days and hours, instead of always calculating one from the other. This gives payroll and HR processes more accurate balances for leave types where day-based and hour-based tracking need to differ.
Original PR description
[IMP] hr_holidays: track time off balance in both days and hours Adds a generic extension point so a leave type's day/hour balance can be tracked as two independent counters instead of one derived from the other: - Extracted the per-work-entry-type leave consumption loop into _consume_leaves_for_work_entry_type, operating on a list of `LeaveCounter` (a way to track both days and hours for some specific tome types) - Added _get_consumed_leaves_extra_counters(work_entry_type), empty by default: a module can register additional counters consumed in the same FIFO pass as the primary one. Only the primary counter (the type's own unit_of_measure) can block a request; extra counters never block, they just go negative on the last allocation touched instead (see l10n_be_hr_payroll). - Renamed `number_of_hours_display` to number_of_hours on hr.leave.allocation, now that it not just derived from number_of_days. Task-6212208
Enhancements to existing features
Financial reports can now prioritize key summary lines before limiting how many details are shown. This helps ensure important lines such as initial balances remain visible when users expand reports like the General Ledger or Partner Ledger.
Original PR description
This key allows defining a sort function on custom groupbys that will be used to reorder the grouping keys returned by this groupby when calling _expand_unfoldable_line_with_groupby, before the load_more_limit is used to limit the number of groupby results that will actually generate lines. Thanks to this, we can rely on a custom groupby to compute initial balances as a dedicated snapshotted engine summed with another in an aggregation, and still have the guarantee the "initial balance" groupby line will be returned as the first result (we needed that while refactoring General Ledger and Partner Ledger, so that they can benefit from snapshots). Without it, it was possible the "initial balance" line got cut by the load_more.
Resolved issues and error corrections
This fix ensures invoices sent to ZATCA are properly marked as submitted even when the user only has read-only access to journals. This prevents the same invoice from being sent again accidentally, reducing duplicate submissions and reconciliation issues.
Original PR description
**Steps to reproduce:** This issue is hard to reproduce because it requires a live ZATCA connection: - As a user with read-only permission on journals, send an invoice to ZATCA. - You get an access error on the journal, and the invoice is unchanged (You can try sending it again to ZATCA). **Issue:** What happens is: - A user with read-only permission on journals sends an invoice to ZATCA. - If ZATCA responds with a 200 (successfully submitted), we try to write on the field `journal.l10n_sa_latest_submission_hash` - With no write permissions, the write fails and all changes are rolled back (on odoo, not on ZATCA) - We can send the invoice again to ZATCA, resulting in duplicates. **Solution:** - Added a sudo when writing on the field: `journal.l10n_sa_latest_submission_hash` opw-6320179 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287081 Forward-Port-Of: odoo/odoo#278728
Features or functions removed from Odoo
Code cleanup and technical improvements
This update simplifies how Odoo's messaging features react to data changes, making chat, live chat, and discussion views more reliable and easier to maintain. It also fixes cleanup and counter-loading issues that could affect guest chat sessions and messaging menu behavior.
Original PR description
Before this commit, a field reacts to its own updates through the onUpdate option of its declaration. There is no need for that option, as the record now offers record.onChange(dependencies,…
Before this commit, a field reacts to its own updates through the onUpdate option of its declaration. There is no need for that option, as the record now offers record.onChange(dependencies, callback) for the same thing. This commit declares those reactions in setup() and removes the option with its machinery: the callbacks the model keeps per field, the observer each record registers for them, and the queue that holds the calls until the end of the update cycle. They run synchronously, once the write that changed a dependency is applied, so a callback reads a complete record and the first run of a new record sees its inserted values. A callback that would act on the default of a field before its compute or its payload lands skips its initial run. The discuss sidebar now picks its tab in setAsDiscussThread(), where the tabs of the thread are settled, rather than in a reaction to the thread. This also fixes the guest token cleanup, which deleted the channel of the new token rather than the one it had added, and stops a tab that left the menu from fetching its counters. https://github.com/odoo/enterprise/pull/130797
Mass mailing users can now save campaigns as reusable templates and manage them from a dedicated Templates menu. This makes it easier to standardize future mailings, reuse proven designs, and preview templates more reliably.
Original PR description
Overview ------ This commit introduces the mailing templates in mass mailing. Before this commit, the only way to save a mailing as a template is to set it as favorite so that it will appear in the…
Overview ------ This commit introduces the mailing templates in mass mailing. Before this commit, the only way to save a mailing as a template is to set it as favorite so that it will appear in the theme selector alongside the common themes. Setting a mailing as favorite does not create a new mailing (template) it only set the favorite flag to true. This commit extends the favorite behavior and adds a complete template library, where the mailing can be saved as a true template, and hence a new mailing (with is_template=True) is created and listed under the `Templates` menu. Specification ------ - Remove the 'favoritism' from mailing.mailing: this includes the favorite star icon and the favorite field. - Add a cog menu item in the form view to save a mailing as a template. - Using a template (clicking on the `use this` button) will create a new mailing out of that template. Technical Notes ------ In order to have a proper display of the templates in the kanban view, we had to add a few things: - Load the kanban renderer inside an iframe: this will help isolate the html content of the templates from the outer Odoo one. -> Better for security and customized stylesheets load. - Wrap the renderer component in a wrapper component to make the reload smoother at every props update; the rationale behind this is to avoid reloading the whole iframe, which is a costing operation with all the stylesheets being refetched, at every props update. task-5358279 subtask-6110541 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Thai localization now creates compliant tax invoices for VAT sales and receipts, including cases where tax is due on invoice or on payment. Users get separate numbering, a dedicated tax invoice print action, clearer PDF details, and an invoice page to manage generated tax invoices, while older simplified print options are removed.
Original PR description
For VAT-registered sellers, tax invoices must comply with the Revenue Code and Revenue Department regulations. A tax invoice can also serve as a standard invoice or a receipt, so support is required…
For VAT-registered sellers, tax invoices must comply with the Revenue Code and Revenue Department regulations. A tax invoice can also serve as a standard invoice or a receipt, so support is required for both invoice and payment-based tax invoicing. - Create TINV tax invoices when posting invoices containing invoice lines with tax_exigibility='on_invoice'. - Create RCT tax invoices for payments when reconciling payments against invoice lines with `tax_exigibility='on_payment'`, including both full and partial payments. - Use independent numbering sequences for TINV and RCT tax invoices. - Add a dedicated action to print Thai tax invoices. - Display the tax invoice number, date, payment information, and tax breakdown on the PDF. - Support the appropriate tax invoice lifecycle for invoice posting, payment reconciliation, and cancellation. Note: - Initially, in the TH localization, we only added 'Tax' as a prefix to the invoice PDF title to indicate that it was a tax invoice. To print the regular invoice PDF, we provided a separate Commercial Invoice print option. - With this task, we are introducing a complete Thai tax invoice feature. As part of this change, we are removing the old template that only added the 'Tax' prefix to the PDF, since it is no longer needed. - We are also removing the Commercial Invoice print option from the menu. The normal Print PDF button will now print the standard invoice PDF. - To manage and print tax invoices, we have added a new page to the invoice form view where users can see all the tax invoices generated for the invoice and print their corresponding PDFs. - As a result, we are removing the old tax invoice templates and introducing new templates specifically for printing the complete Thai tax invoices. Upgrade: https://github.com/odoo/upgrade/pull/11191 task-[6384295](https://www.odoo.com/odoo/project/967/tasks/6384295)
Belgian payroll now supports the 281.30 and 274.30 declarations used mainly for reporting presence tokens. Businesses can also mark employees to be excluded from existing .10 and .20 declarations and included in the new .30 declaration instead, improving compliance coverage for Belgian payroll reporting.
Original PR description
This commit introduces the 281.30 and 274.30 declarations to the Belgian payroll localization. Those declarations are used mainly for reporting presence tokens (jetons de présence). There was also an option added for the version where an employee can be excluded from .10 and .20 declarations, and be included in the .30 declaration instead. task-6147823
Commissions can now be calculated on point of sale orders, using either quantities sold or sales amounts. This aligns point of sale commission tracking with the existing sales order process and also corrects a reporting issue for invoice-based commission data.
Original PR description
This new bridge module allow to compute commissions based on quantity sold or amount sold in pos.order. The behavior is similar to what we do with sale.order task-6391378
Odoo now supports submitting Pakistan customer invoices and debit notes to the Federal Board of Revenue through Odoo's proxy service. Businesses can validate partner registration, complete required compliance checks, store FBR references and responses, and print QR codes on invoice reports for compliant e-invoicing.
Original PR description
Add support for submitting customer invoices and debit notes to Pakistan's FBR (Federal Board of Revenue) via Odoo's proxy service. Add a button that lets users check a partner's FBR registration status. Sending is blocked by compliance checks until required parameters are set. Once posted to FBR, the request/response and FBR reference are stored and printed with a QR code on the invoice report. Onboarding support is also included to run FBR's required sandbox test scenarios needed to whitelist the database. see odoo/iap-apps#1168 task-2879519
Chilean electronic invoicing now supports branches that operate under the same legal entity as their parent company. Branches can share official folio ranges and certificates, roll over to new ranges correctly, and receive incoming documents routed to the right branch.
Original PR description
A branch is the same legal entity as its parent: it shares its RUT, SII registration and certificate, and issues folios out of the ranges the SII granted that RUT. CAFs, folio counters and the localization config were scoped to a single company, so branches could not issue at all. Resolve the legal entity a company issues under and read it wherever a DTE states the issuer, draw folios from the first range still in use so branches sharing a range continue one series and a spent range rolls over to the next, and route incoming documents to the branch named in `CdgIntRecep`. A company ever granted a range of its own never falls back on the one above it, so a branch out of folios is asked for a new CAF instead of consuming its parent's. upgrade: odoo/upgrade#10893 task-6218881
This update improves the email sending experience by clearly warning users about invalid addresses, failed deliveries, and required Gmail or Outlook settings. It also makes resending, replying, forwarding, and signature handling more reliable and easier to understand.
Original PR description
- Add a toast notification when an invalid email address is entered while sending a message. Previously, nothing happened, which could confuse users. - Make the smtp_user field required when…
- Add a toast notification when an invalid email address is entered while sending a message. Previously, nothing happened, which could confuse users. - Make the smtp_user field required when smtp_authentication is set to gmail or outlook. - Add a cancel icon when email delivery fails instead of only changing the icon color. This improves accessibility for colorblind users. - Add hover text to the email delivery failure icon to clearly indicate the failure. - Add a Send Again action that opens the composer with the same message and recipients as the original email. - Include the user's signature by default in the message body when the composition mode is mass_mail. Previously, the signature was missing in this mode. - Restructure the composer body for Reply All and Forward actions in the following order: 1 Message 2 Signature 3 Quoted/mentioned content - Make the delimiter `-- <br>` not editable in the signature block to prevent user from breaking its structure. Previously, text typed there used to end up inside the signature container, where it was hidden behind the collapsed ellipsis in the chatter. - Rebuild the signature layout after each edit so the "--" line and the signature itself always stay in separate blocks. Editing around the delimiter, such as deleting a line, could leave the signature in a broken state. Task-6321967
Update notifications now include counts for light users, giving businesses a clearer view of user types during update checks. This helps administrators better understand licensing or user composition information alongside existing update details.
Original PR description
This commit add the light users counts to the update notification. Task-Id: 6388209 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Point of Sale can now record daily session closing entries in a dedicated journal while keeping customer invoices in the usual sales journal. This helps businesses meet localization and e-invoicing requirements where closing entries must be separated for compliance or reporting.
Original PR description
Multiple l10n require edi with a daily pos closing journal different from the default journal. task-id: 6446274 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The SMS sending flow is now closer to the email composer, with clearer recipient styling, better character count feedback, easier template use, and support for scheduling SMS messages. This helps users prepare, reuse, and send SMS communications with more confidence and less friction.
Original PR description
This PR implements a series of UI/UX improvements for the SMS module. The goal is to align the SMS sending flow with the Mail composer experience and provide better feedback during account registration. See sub commits for more details. task-6178288
The Bank Reconciliation Summary now gives finance teams a fuller view by showing both reconciled and unreconciled bank activity, including partially reconciled items. It also adds clearer balance checks, line-level warnings, and a period-based layout so users can more easily spot mismatches between bank balances and the general ledger.
Original PR description
- Structure of the report would be like below:- - Bank Account Name - Opening Bank Balance - Reconciled Transactions - Reconciled Receipts - Reconciled Payments - Unreconciled Transactions -…
- Structure of the report would be like below:-
- Bank Account Name
- Opening Bank Balance
- Reconciled Transactions
- Reconciled Receipts
- Reconciled Payments
- Unreconciled Transactions
- Unreconciled Receipts
- Unreconciled Payments
- Misc. operations
- Calculated Ending Bank Balance
- Ending General Ledger Balance
- Outstanding Receipts/Payments
- Outstanding Receipts
- Outstanding Payments
- The main change in the report is that report now shows both reconciled and
unreconciled transactions. (Before this commit it displayed only unreconciled
transactions.)
- Reconciled transactions will report reconciled amount of the transaction and
Unreconciled transactions will report residual amount of the transaction.
So partially reconciled transaction will appear twice in the report.
- Opening bank balance = last statement before period's starting balance
+ that statement's transactions before period
+ transactions without statement before period
- If we don't find any transactions before period, then we'll look for period's
first statement and take its starting balance as opening bank balance.
- Opening bank balance will redirect to transactions used in above calculation.
- If opening or calculated ending bank balance mismatches with GL balance as of
that day, an error icon with warning message tooltip will be added on that
respective lines and that error icon will redirect to General Ledger.
- Similar warning icon will be added on Misc. Operations line if there are any
misc operations and that icon redirects to that misc entries.
- Before this commit misc entries line only reported total balance and that
balance redirected user to misc entries, but with this commit that misc entries
are now added in this report itself like transactions and redirect on misc
balance has been removed.
- A new warning at top of the report has been added for transactions without
statement and warnings for GL mismatch and misc entries have been moved from
there to related report line.
- Change reconciliation report name from `Bank Matching` to
`Bank Reconciliation Summary`.
- Replace the current date selection with period selection, with previous month
selected by default.
- Enable `Add totals below sections` setting for this report.
- Remove journal groups from report options, as this report is mainly about Bank
Journal from which this report was opened.
- Remove `Currency` column from the report as `Amount Currency` column's amounts
will be already formatted with their respective currencies.
- Remove red color from negative amounts, as they are just outgoing payments
and by looking at red color user will assume that there is something wrong with
that payments.
- Opening balance, ending balance and GL balance lines will be always visible
even if filter `Hide lines at 0` is applied. Same logic is applied for misc
entries but only if we have misc entries.
UPGRADE PR: https://github.com/odoo/upgrade/pull/10951
[task-4638579](https://www.odoo.com/odoo/project/967/tasks/4638579)This update removes an obsolete option from the Bulgarian SAF-T file attachment error wizard. It keeps the tax reporting workflow aligned with recent validation changes and reduces unnecessary internal complexity, with no expected impact on everyday users.
Original PR description
bypass_failing_tests has been removed from the definition of the tax return action_validate since 19.4. Thus the file_attachment_error_wizard no longer needs to hold that value. This commit removes it in master. Related: odoo/upgrade/pull/11272 Related: odoo/enterprise/pull/118326
Timesheets can now record time spent in Google Chat even when no specific chat participant is selected. This helps ensure more complete and accurate time tracking for work done through Google Chat.
Original PR description
This commit's purpose is to add a new rule to be able to record the time spend on google chat when no specific chatter is selected. task - 6455607
Before this commit, ts assistant was didn't have any rules to detect the usage of Zoom After this commit, ts assistant should come with pre-build rule to track Zoom use in both web and application form. task-[6518921](https://www.odoo.com/odoo/project/4105/tasks/6518921)
Original PR description
Before this commit, ts assistant was didn't have any rules to detect the usage of Zoom After this commit, ts assistant should come with pre-build rule to track Zoom use in both web and application form. task-[6518921](https://www.odoo.com/odoo/project/4105/tasks/6518921)
Changes to a stock transfer's effective date will now be recorded in the chatter when the transfer is unlocked. This improves traceability by making date adjustments visible in the transfer history for audits and follow-up.
Original PR description
Effective date is allowed to be changed if transfer is unlocked. But if it is changed, it is not reflected in chatter, which leads to poor tracebility. This commit adds tracking for the field. task-6116292 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
Singapore localization now includes Peppol e-invoicing support in preparation for upcoming national requirements. The change adds Singapore-specific document registration and identifier handling while keeping public registration disabled until required verification steps are ready.
Original PR description
Singapore will mandate e-invoicing over Peppol for all businesses in the coming years, so Peppol is part of the Singapore localization rather than an optional add-on. Make l10n_sg depend on…
Singapore will mandate e-invoicing over Peppol for all businesses in the coming years, so Peppol is part of the Singapore localization rather than an optional add-on. Make l10n_sg depend on account_peppol accordingly. SG is deliberately left out of PEPPOL_DEFAULT_COUNTRIES, and of the countries of the account_peppol manifest, for the time being. We do not want anyone registering before the KYC step is deployed on the access point. Adding SG to both is all that will be left to enable it. Declare the SG-specific Peppol document types so that they are registered on the access point: SG PINT from l10n_sg_ubl_pint, and BIS Billing International 3.0 from l10n_sg, the latter being needed to keep receiving invoices sent in the legacy InvoiceNow format. Registration happens through account_peppol's auto register services cron, triggered from the post-init hook of both modules on installation, and also when an SG company (EAS 0195) first transitions to receiver state. The matching uninstall hooks deregister the services again. Accept the participant identifiers under which the SGNIC SMP registers Singapore participants for Peppol scheme 0195: 'SGUEN' and 'SGUXN' followed by a UEN, along with the 'SGTST'/'SGGST' test identifiers and the 'XXUID' universal identifiers. Also hide the participation role setting for SG companies, as the role is not selectable there. task-5024393
This update strengthens Odoo's internal linting so developers can detect methods that claim to extend parent behavior when no parent method exists. It also removes or relocates unused code across several apps, reducing maintenance risk without introducing major user-facing changes.
Original PR description
Find all methods in the MRO that call `super` but don't exist in the parent class. Check `__override` value on methods. There is a simple default we can use: `__code__.co_names` contains "super" if `super(...)` is used in the function. That may flag manual calls to other methods that the current once, but setting the override flag on the function can whitelist it. task-2922186 https://github.com/odoo/enterprise/pull/130760 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update improves the website builder interface so common editing actions are easier to understand and use. It makes color selection clearer, keeps controls properly aligned in different languages, improves warnings for theme and page changes, and polishes several visual elements.
Original PR description
Improve the UI of the builder by fixing some issues and standardize options layout task-6259086
The web interface now separates status bar styling from unrelated switcher styling. This reduces the risk of visual conflicts and helps keep the user interface consistent as different navigation controls evolve.
Original PR description
`.o_switcher` is not related to this component and is now problematic, as we have specific slide styling for the view switcher. The design should be better separated and more clearly split into distinct parts. task-6546246 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update improves the visual clarity of buttons in Odoo forms by keeping borders fully visible when users hover over or focus on them. It also makes the focus indicator in the "More" dropdown more consistent, supporting easier navigation and better usability.
Original PR description
Prior to this commit, the button border could be partially obscured when the button was hovered or focused. This commit ensures that the entire border remains visible in these states. This commit…
Prior to this commit, the button border could be partially obscured when the button was hovered or focused. This commit ensures that the entire border remains visible in these states. This commit also reviews the focus ring for buttons within the "More" dropdown to ensure it remains consistent and clearly visible. task-6528444 Requires: - https://github.com/odoo/enterprise/pull/130674 | Before | After | |--------|--------| | <img width="305" height="120" alt="Screenshot 2026-09-08 at 11 47 42" src="https://github.com/user-attachments/assets/6374fcb1-cf48-46f3-b467-64dbff1b2011" /> | <img width="297" height="113" alt="Screenshot 2026-09-08 at 11 48 05" src="https://github.com/user-attachments/assets/face6b7a-28ab-4308-ae78-3689c45da948" /> | | <img width="443" height="122" alt="Screenshot 2026-09-08 at 11 47 47" src="https://github.com/user-attachments/assets/4db5ac90-226e-44e3-8185-5f14b205476d" /> | <img width="484" height="119" alt="Screenshot 2026-09-08 at 11 48 06" src="https://github.com/user-attachments/assets/8d2a5ff3-ff4a-4947-b5d9-7a4277548b3e" /> | | <img width="268" height="219" alt="Screenshot 2026-09-08 at 11 46 18" src="https://github.com/user-attachments/assets/e5dbbe3d-d0e7-440e-a61e-53574f0d8896" /> | <img width="327" height="235" alt="Screenshot 2026-09-08 at 11 46 11" src="https://github.com/user-attachments/assets/632ceefc-9135-43f9-b404-fc18f9f4187c" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now send pending Indian e-invoices directly from the invoice list opened from the dashboard. This reduces extra navigation and makes it easier to complete e-invoicing tasks from the pending items view.
Original PR description
Currently, users can see the number of pending E-invoices on the dashboard, but cannot easily send them from the resulting list. This commit adds a "Send" button to the invoice list view, allowing users to easily proceed with creating E-invoices. The dashboard action is also updated to open this specific list view. task-6545498
Users selecting a working schedule can now see visual indicators and a preview of daily hours before choosing. This helps teams pick the right calendar more confidently and reduces mistakes when configuring work schedules.
Original PR description
Add visual indicators and a preview of each working schedule's daily hours, to better inform the selection of calendars. Task ID: 6348656
Selection highlights now slide consistently across more switcher controls, not just the main view switcher. This makes navigation feel more polished and avoids distracting overshoot in larger button groups.
Original PR description
The travelling indicator was painted for the view switcher only, which is handed its button count and its active index by the control panel. Paint it for every `.o_switcher`: `:has()` on the group reads both from the buttons themselves, one rule per position, up to three buttons. `@starting-style` stays on the view switcher alone. It is needed where the group is rebuilt between the two states, and everywhere else the group survives the change, so the move starts from the position already painted. Two groups are left out. '.o_statusbar_status' wraps each step in a div and marks the current one with a class of its own, so neither number can be read off the group. '.o-mail-ActionList-group' holds toggles that can all be off, and with no active button the layer would sit on the first one as if it were selected.
Buttons in form statistic areas now use a consistent background color across normal and hover states. Dark mode colors were also adjusted so hover feedback is easier to see, improving visual clarity for users.
Original PR description
This commit ensures that all `oe_stat_button` elements use the same background color in both their default and hover states. This commit also fine-tunes the colors for dark mode to make the hover…
This commit ensures that all `oe_stat_button` elements use the same background color in both their default and hover states. This commit also fine-tunes the colors for dark mode to make the hover state more visible. task-6528444 Requires: - https://github.com/odoo/odoo/pull/286952 | Before | After | |--------|--------| | <img width="239" height="78" alt="Screenshot 2026-09-08 at 14 44 47" src="https://github.com/user-attachments/assets/e9a87f3f-598d-447a-a992-7458fe4baaf8" /> | <img width="199" height="90" alt="Screenshot 2026-09-08 at 14 44 13" src="https://github.com/user-attachments/assets/8de5ab01-08c4-43ac-96a8-5e1fa53e0dc8" /> | | <img width="223" height="71" alt="Screenshot 2026-09-08 at 14 45 01" src="https://github.com/user-attachments/assets/8bf329cb-a73a-425c-a619-d66d2e96ccc3" /> | <img width="247" height="92" alt="Screenshot 2026-09-08 at 14 43 10" src="https://github.com/user-attachments/assets/e55435d9-b54e-479d-8ba1-efccb665e9c1" /> | | <img width="231" height="81" alt="Screenshot 2026-09-08 at 14 44 36" src="https://github.com/user-attachments/assets/024bd44d-4c91-468a-9575-defe97c6dbb8" /> | <img width="228" height="79" alt="Screenshot 2026-09-08 at 14 44 27" src="https://github.com/user-attachments/assets/a0d7c009-5a36-478a-868e-335b1609b8d2" /> | | <img width="234" height="324" alt="Screenshot 2026-09-08 at 14 45 07" src="https://github.com/user-attachments/assets/fb9ef801-78eb-483c-912f-3b51a84c4c6c" /> | <img width="278" height="361" alt="Screenshot 2026-09-08 at 14 43 04" src="https://github.com/user-attachments/assets/9a982250-2b67-40e3-850a-9102ce187f0f" /> |
Belgian payroll users now get clearer visual cues and daily-hour previews when choosing employee working schedules. This helps HR teams compare schedules more easily and select the right calendar with greater confidence.
Original PR description
Task ID: 6348656
The Click and Collect option on the online store has been redesigned into a clearer radio-style selector. This makes pickup availability easier for shoppers to understand and helps create a smoother checkout experience.
Original PR description
task-6514854 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update improves how Odoo handles editing field definitions in web views. It introduces a shared mechanism that lets forms better control whether fields can be edited, making the editing experience more consistent and reliable for users configuring views.
Original PR description
The fieldEditionPlugin is used by field.js It is a global plugin because we cannot control where field.js is used The plugin allows for editing a **field definition**, not the content or value The formView reinstanciates it, giving it some control. The plugin instanciates items from a registry that each tell whether a field is editable or not. 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
Odoo now uses the same internal name for the X social media icon across website, email, marketing, forum, sales, and e-learning areas. This small cleanup helps keep branding consistent and reduces confusion when maintaining social sharing and social media templates.
Original PR description
*: iap_mail, marketing_card, mass_mailing, website_forum, website_sale, website_slides This commit homogenizes the name of the X icon.
Users can now compare delivery carrier prices directly when choosing a carrier, instead of calculating each option one by one. Prices can be refreshed when order weight changes, making it easier to choose the best shipping option and reducing manual work.
Original PR description
Before, people had to go 1 by 1 for each carrier to calculate the cost and pick the cheapest one. This is not user-friendly, which is why now, in the carrier selection we can directly see the price, which is recalculated each time when total weight changes. Also, cost are now also visible in the list view, when "Search more..." button is clicked on the carrier selection. A separate view was created specifically to ensure that on other views this column is not there. Calculated delivery prices are passed via the context to this view. task-6276527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Belgian payroll now tracks legal leave in both days and exact hours, reflecting that different workdays can have different lengths. This improves visibility for employees and payroll teams by warning when the hour balance goes negative, while keeping the existing day-based blocking rules.
Original PR description
[IMP] l10n_be_hr_payroll: track legal leave balance in days and hours Belgian legal leave (and its N-1/N-2 postponed counterparts) is entitled in days, but the hours behind those days can vary by…
[IMP] l10n_be_hr_payroll: track legal leave balance in days and hours Belgian legal leave (and its N-1/N-2 postponed counterparts) is entitled in days, but the hours behind those days can vary by schedule (a short Friday isn't worth the same as a Monday). Uses hr_holidays' _get_consumed_leaves_extra_counters to track an exact hour counter alongside the existing day counter for these 3 types: taking a day off reduces hours by the real hours worked that day (or the average, for employees without a defined daily schedule), while the day counter still reduces by 0.5/1 as before. The day counter still blocks; the hour counter only warns, on the payslip and on the leave request, when it goes negative. Also reworks how days/hours are computed for these 3 types: - Payrun allocation (l10n_be_hr_payroll/wizard/hr_payroll_allocating_paid_ time_off.py): the number of days allocated is now based on the employee's days/week (4 weeks x days/week), not on hours/day, hours are computed independently rather than derived from the rounded day count, and are capped at the lower of the previous and current employer's absolute hours/week rather than their reference calendars. - Adds "Accrued Hours"/"Accrued Days" columns to the December payrun's Holiday Pay step. - Holiday attestations (l10n_be_holiday_attest.py): same hours-first, capped-at-the-lower-rate logic for hours/days carried over from a previous employer's certificate. - Time Off Dashboard card/popover and the leave form's Summary panel show the exact hour balance, muted, only when it actually disagrees with the rounded day-based estimate shown everywhere else. Task-6212208
Belgian payroll calculations now reflect the 2026 rules for intellectual property income, including ONSS exemptions, withholding tax limits, yearly caps, and artistic certificate cost treatment. This helps payroll teams apply the correct employee remuneration split and reporting rules automatically.
Original PR description
Since 2026, the intellectual property (IP) is exempt from ONSS up to 30% of the total remuneration (DmfA code 47), unless the ONSS contributions are forced on the contract (default). The IP withholding tax (15%) only applies within that share and while the average IP of the 4 previous years stays under the yearly limit (77220€ in 2026); the lump-sum costs only remain for the owners of a certificate of artistic work. The IP paid in the year is capped on the yearly limit, the exceeding part being a regular remuneration. The rule cp200_employees_salary_ip_part_onss becomes generic: ONSS on the remuneration exempt from withholding tax (category ONSS_NO_WT).
Marketing Automation now includes a template library so users can browse, create, and reuse mailing designs directly within campaign activities. Campaign mailings are easier to find and manage, including better access to automation mailings and corrected links when duplicating campaigns.
Original PR description
Overview ------ This commit adds the mass_mailing's template library to marketing_automation. Specs ------ The addes features are: - Add the `Templates` menu which lists the mailing templates. Note: the templates listed here are only for the models that work for marketing campaign. e.g., `mailing.list` templates are filtered out. - When creating an activity, a design button is added that allows to design a new template. Once set, the template is readonly. This PR is linked to a community PR. task-5358279 subtask-6110541
AI live chat now supports a guest-only access mode that aligns it with the broader live chat platform. This helps ensure website visitors can use chat flows without needing a logged-in account, improving consistency and reducing access friction.
Original PR description
Enterprise counterpart of "[IMP] im_livechat, *: add force_guest auth method", which explains the why. task-6259734 https://github.com/odoo/odoo/pull/267142
Turkish payroll now supports tax relief for eligible R&D and Design Center employees. The change applies stamp tax exemptions and income tax reductions up to the legal wage ceiling, helping businesses calculate payroll incentives more accurately.
Original PR description
Add tax relief incentives for R&D/Design Center employees. Employees qualifying for the incentive receive tax relief on wages up to 40 times the gross minimum wage: - Full stamp tax exemption up to the ceiling. - Income tax relief based on certificate level: 95% for doctorate, 90% for master's, and 80% for other levels. - Standard taxation on the portion exceeding the ceiling. task-6434855
Timesheet suggestions from Gmail and calendar items now look across a customer’s related company/contact structure to find the most recently used project. This reduces random or incorrect project matches and helps users log time faster with better defaults.
Original PR description
Before this commit: - Gmail emails are resolved to a random timesheeted project linked to a partner having the same email - Calendar events are resolved to the most recent timesheeted project linked to partner_ids In this commit: - Instead of looking to the partner, the most recent timesheeted project is taken from the partner tree (child_ids, parent_id) task-6254947 Forward-Port-Of: odoo/enterprise#128801
The Discuss header now uses browser styling instead of background scripts to size its input fields. This simplifies the interface logic and should make the header more reliable and easier to maintain without changing the user workflow.
Original PR description
Currently, the discuss header size is computed in JS. Code is not easy as it has to account for every participing node. This commit replaces this computation by a CSS only solution: - size the input based on an ::after element, containing the text of the input. - remove the inputs from the layour flow as to not impact sizing at all. 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
The survey dashboard layout has been refined to present information more clearly, including better handling when surveys are grouped. This improves readability and consistency for users managing surveys across Survey, CRM, and eLearning-related workflows.
Original PR description
This commit fine-tunes the layout of the survey dashboard. To achieve this, it also introduces the new `customClasses` prop for the progress bar field, allowing for better layout customization.…
This commit fine-tunes the layout of the survey dashboard. To achieve this, it also introduces the new `customClasses` prop for the progress bar field, allowing for better layout customization. Additionally, it detects whether the survey Kanban view is grouped and adapts the layout accordingly. task-6512763 Co-authored-by: Adrien Dieudonné <adr@odoo.com> | Before | After | |--------|--------| | <img width="1918" height="902" alt="Screenshot 2026-09-04 at 17 01 35" src="https://github.com/user-attachments/assets/dca94109-23e0-4130-824b-c9117b6de965" /> | <img width="1915" height="864" alt="Screenshot 2026-09-04 at 17 02 23" src="https://github.com/user-attachments/assets/ce3a74df-279a-4fa4-9671-01a5f50d08dd" /> | | <img width="1919" height="906" alt="Screenshot 2026-09-04 at 17 01 47" src="https://github.com/user-attachments/assets/20c2e134-c8d6-4a54-9fc9-da51b8890ea0" /> | <img width="1914" height="807" alt="Screenshot 2026-09-04 at 17 02 33" src="https://github.com/user-attachments/assets/6e6b73c4-ea7c-45ea-a43e-912500e7826e" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now enrich a contact's company information directly from the actions menu. The enrichment process searches using the most reliable business identifiers first, then falls back to email or website, helping teams complete partner records faster and more accurately.
Original PR description
this commit will add a new server action to enrich a partner from the cog menu. We firstly check the duns number since it's something more precise. Then, we use the different identifier like vat, siret, siren (in that order). And then the email and website. task-6389091 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
VoIP users can now choose call forwarding with a simpler Forward or Don't Forward option, then pick internal destinations or external phone numbers from one place. This makes forwarding easier to configure and prevents one forwarding update from accidentally clearing other saved forwarding settings.
Original PR description
## Summary This PR simplifies the busy and no-answer forwarding settings. Users now choose between "Forward" and "Don't Forward". When forwarding is enabled, internal destinations and external phone numbers are selected from the same destination list. It also fixes an issue where updating one forwarding field on `res.users` could clear the other forwarding values stored on `res.users.settings`.
This update refreshes the spreadsheet interface components related to carousel-style data viewing. Business users may see a more up-to-date or improved spreadsheet experience, although the pull request details do not describe a specific workflow change.
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
This update reorganizes how automatic leave approvals are handled in the Time Off app by moving that logic into its own dedicated method. The change should make future maintenance and enhancements easier without changing the day-to-day experience for employees or managers.
Original PR description
task-6384703 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
Margin reporting screens are now easier to read and focus on the information users need. Forecast margins gain clearer pivot and graph analysis, while actual margins remove unrelated timesheet filters and use more relevant default groupings.
Original PR description
This commit cleans up the Actual Margins and Forecast Margins views to improve readability and remove irrelevant timesheet/accounting elements. Forecast Margins (sale.report): - Added a bar graph view (measured by margin, grouped by customer). - Added a pivot view (measures: untaxed total, expected cost, margin). - Reordered views to: list, pivot, graph, kanban. - Added 'Project' field and 'Project' group by to the search view. Actual Margins (account.analytic.line): - Reordered views to: pivot, graph, list, kanban. - Set default group by to Account and Billing Type. - Cleaned the search view by removing timesheet-specific filters (mine, billable, non_billable, parent_task_id, department, etc.) that do not apply to the margins context. task-6456183
Product names are no longer mixed into line-item descriptions on sales orders, purchase orders, and invoices. This makes descriptions clearer, improves electronic document exports, and reduces inconsistent behavior across related business documents.
Original PR description
Sale order lines, purchase order lines, and account move lines currently store the product's display name together with its description in the `name` field. This behavior was originally introduced so…
Sale order lines, purchase order lines, and account move lines currently store the product's display name together with its description in the `name` field. This behavior was originally introduced so the product field could remain hidden while still displaying both the product and its description in a single field. Maintaining this behavior requires a significant amount of JS logic and has led to several inconsistencies across the different models. Now that the framework supports stacking multiple fields in the same column, this workaround is no longer necessary. Keeping the product name in the description also has several drawbacks: - Product names are unnecessarily exported as EDI descriptions. - The description field always contains a value, making it impossible to tell whether a custom description was actually provided. - Models such as sale order templates do not follow the same convention,resulting to complex logic to make it work. - The JS widget needs complex logic to strip the product name while taking translations into account. - The product/description logic has become tightly coupled with the sections widget, making it difficult to maintain. This commit stores only the product description in the `name` field and introduces a new non-stored computed `label` field on sale order lines, purchase order lines, and account move lines. The `label` field combines the product display name and description and is used wherever both pieces of information need to be displayed, such as reports, the portal, and list view seachable text field introduced in d069ce59e28fda2bc25fb89fd01ee7b988a30fa0. For sale, the extra logic required to preserve the product name across sale orders and sale order templates is removed, allowing the `name` field to be used consistently as the product description. For purchase, the seller-specific naming logic is removed from the compute methods and delegated to the product display name retrieval. For accounting, EDI exports now contain only the actual line description instead of the product name followed by the description. This PR is the first step towards adapting the new framework `<column>` support for the product and description field, allowing the remaining JS logic to be significantly simplified in follow-up PR. task-6241473 See Also: - https://github.com/odoo/enterprise/pull/122792 - https://github.com/odoo/upgrade/pull/10919 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Merchants can now control whether product reference prices, such as price per kilogram, appear separately for each website. This prevents a setting enabled for one online store from automatically affecting other websites in the same database, supporting different pricing display needs across brands or markets.
Original PR description
The "Product Reference Price" setting, which adds a reference price per unit of measure on product pages (e.g. $/kg), was controlled by the group `product.group_show_uom_price`. As this group is…
The "Product Reference Price" setting, which adds a reference price per unit of measure on product pages (e.g. $/kg), was controlled by the group `product.group_show_uom_price`. As this group is shared across the database, enabling the setting on one website enabled it on every website, which doesn't fit merchants running several websites with different display requirements. This commit adds a `show_product_reference_price` field on `website`, exposed on `res.config.settings` through a related field, and switches the controller, `product_template`, and cart template logic to check it instead of the shared group. The underlying `product.group_show_uom_price` group is still granted to `base.group_user` when the website setting is enabled, since the base unit price computation on `product.template` still depends on it, but it is no longer revoked when the setting is disabled on a website, so as not to affect other websites relying on it. task-6340943 See also: - https://github.com/odoo/upgrade/pull/10838 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Calendar screens are easier to read and navigate, with duplicate meeting entries removed, clearer hover and availability indicators, and improved reminder notifications. Contacts now show meeting information directly, helping users quickly find upcoming or past meetings with a customer or partner.
Original PR description
Purpose --- This commit aims at improving the UX of the calendar module Specs --- - Meeting activities were displayed 2 times in the calendar, as an activity in the header of the day as well as an…
Purpose --- This commit aims at improving the UX of the calendar module Specs --- - Meeting activities were displayed 2 times in the calendar, as an activity in the header of the day as well as an event. Now only the event is displayed to avoid confusion. - Switches the default reminders view from list to kanban. Each card displays the type of reminder, the time before the event and the name of the reminder template. - Adds a search view to group reminders given their type. - Adds a grey pill when hovering over date in calendar view. - Adds a stat button displaying in the "res_partner" form indicating the next meeting date and redirecting towards the event upon click. In the case where there is no future meeting but past meetings, the button displays their count (with the exception of leaves) and redirect towards a list view containing all these meetings. If the partner doesn't have any meeting recorded, the button redirects to the calendar. - Fixes "CopyClipboardUrl" not displaying the text to be displayed instead of the URL. Before, the "text" attribute wasn't correctly transfered from "CopyClipboardUrlField" to "UrlField". Now, the "text" attribute correctly appears in the props of "UrlField". --- Task-6293537
Sales order delivery status is now displayed from the Sales app instead of depending on the Inventory-related Sales Stock component. This helps customers see delivery information in the portal even when full stock management is not installed.
Original PR description
The delivery_status field was moved from sale_stock to sale to display the delivery status for the 'stock without stock' logic, even when stock isn't installed. In this commit I merge the sale_stock.portal_my_orders template into the sale.portal_my_orders template. task-6378133
Accounting entries now expose the fiscal position from their related invoice or journal entry. This makes it possible to analyze fiscal position information directly in pivot reports, improving reporting flexibility for finance teams.
Original PR description
We add the relation fiscal_position_id from move_id inside account_move_line. This is used so that we can use it inside a pivot view. task-6508687
Product and sales document cards now show a visual preview, file type icon, or link icon alongside the title. This makes it easier for users to distinguish documents at a glance in kanban views.
Original PR description
Documents were only shown as a title in the kanban card, which made them hard to tell apart. Add back an aside with the image preview, the mimetype icon, or the link icon depending on the document. task-6090002
Odoo can now define the size of pop-up windows directly in the screen layout configuration. This gives teams more consistent dialog sizing across actions and relational field workflows, improving usability without changing day-to-day business processes.
Original PR description
This commit adds the support for the `dialog_size` attribute on the root node of views' archs. When the view is rendered inside a dialog, e.g. action in target="new", many2one "search more"/"create and edit", x2many FormViewDialog...), this attribute is used to determine the size (width) of the dialog. Possible values are those of dialog.js: "sm", "md", "lg", "xl", "fs" or "fullscreen". Before this commit, it was only possible to specify the dialog's size for actions with target="new", by setting the `dialog_size` key in the context. The plan is to convert the usecases to use this new API. Task~6429925 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
Italian electronic invoices now handle cash rounding lines more safely when generating XML. This keeps the required tax information in the invoice output without changing a shared tax calculation process used elsewhere, reducing the risk of side effects.
Original PR description
Remove the override of `_prepare_product_base_line_for_taxes_computation` since it's a low level method used by a lot of flows. Instead, we just add the 0% exempt tax on the line on-the-fly at the generation of the xml. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287016
The breadcrumb trail in Odoo’s web interface has been visually softened by removing bold styling and making separators less prominent. This creates a lighter, cleaner navigation experience without changing functionality.
Original PR description
ENT: https://github.com/odoo/enterprise/pull/130516 task-6527644 | Before | After | |--------|--------| | <img width="750" height="437" alt="Screenshot 2026-09-04 at 16 49 38" src="https://github.com/user-attachments/assets/428ed1f6-52fc-43c7-8ad7-aa87124f988b" /> | <img width="754" height="436" alt="Screenshot 2026-09-04 at 16 48 35" src="https://github.com/user-attachments/assets/c9eb44dd-1d5c-4c79-b0bb-43c41122b3f6" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Odoo now uses the combined product label for invoice, tax, and electronic document outputs after the product name was separated from the description field. This keeps customer documents and local compliance files accurate and consistent across accounting and sales flows.
Original PR description
This PR adapts EDIs and tests to the community change that removes the product's display name from the `name` field. From now on, the product's display name and description are combined in the `label` field instead. task-6241473 See Also: - https://github.com/odoo/odoo/pull/273948 - https://github.com/odoo/upgrade/pull/10919
Margin reports now make profitable and unprofitable totals easier to spot by coloring positive totals green and negative totals red. The margins report search view has also been simplified by removing timesheet-specific filters, helping users focus on margin analysis.
Original PR description
This commit cleans up the Enterprise margins views and introduces specific color coding for margin totals in the grid view. Actual Margins Grid View: - Created a new `margin_analytic_line_grid` js_class. - The grand total and section totals are now colored red if negative and green if positive to quickly highlight margin profitability. - Ensure standard text colors are not overridden by danger/success classes on non-total rows. - Reordered the grid view in the action sequence. Search View Cleanup: - Removed enterprise-specific timesheet filters (my_team_timesheet, my_department_timesheet, my_tasks, nonvalidated, validated) from the margins report search view. task-6456183
Payroll leave records can now show issues and warnings, helping payroll teams spot potential problems before they affect processing. The change also adds country-specific warning support for Belgian and Luxembourg payroll and fixes an upgrade issue in Belgian payroll.
Original PR description
In this commit, we added issues/warnings to hr.leave model. task-6384703
Working files now connect more directly with spreadsheets, letting users open a linked spreadsheet from a working file and insert other views into a working file sheet. Return check screens also receive styling improvements, making the workflow clearer and easier to use.
Original PR description
Better styling for return checks Added spreadsheet integration with working files, we can now access a spreadsheet linked to a working file using the embedded action on the working file. As well as add other views inside a working file sheet using the insert in spreadsheet action.
Payslips created through payroll runs now record which pay run created them and which user started the batch, making audit trails easier to understand. Companies can also disable these automatic creation messages for large payroll batches when performance is a priority.
Original PR description
Payslips log "Pay Slip created" in their chatter without naming the pay run that generated the payslip or the user who ran that batch. `hr.payslip._creation_message()` now names the origin in the log the record already gets: - from a pay run: `Payslip created from the pay run <run> by <user>` - created directly: `Payslip created by <user>` No second message, no extra query per payslip. For batches where even that log costs too much, the `hr_payroll.payslip_run_creation_no_message` system parameter skips it. Off by default. With it on, pay-run payslips get no creation message at all, including the generic one from task 6253290. Task 6530900
Appointment scheduling screens are easier to use with clearer quick creation options, cleaner staff schedules, better reminder grouping, and more informative appointment views. Shared booking links and Gantt date selection behavior were also improved, reducing confusion during everyday booking workflows.
Original PR description
Purpose --- This commit aims at improving the UX of the appointment module Specs --- - In the staff and resource booking views, "appointment_type", "resource_ids" and "user_id" were added to the…
Purpose --- This commit aims at improving the UX of the appointment module Specs --- - In the staff and resource booking views, "appointment_type", "resource_ids" and "user_id" were added to the quick create form. These fields are presets and possibly readonly depending on the way the quik create form was accessed. For example, if the user clicks on an appointment type then "New", the "appointment_type" field will be set to the appropriate value and be readonly, but the resource_ids/user_id will still be editable, however, if the user clicked on a slot, these fields will be readonly in addition to the "appointment_type" field. - Removed the display of time off events in the schedule staff view as the unavailability of the user is already handled internally as well as to keep appointment related events. - Shows the "appointment_type", "appointment_status" and "resource_ids" in the calendar event form view if debug mode is active. Furthermore, if the status becomes "cancelled", the resource fields isn't required anymore. - In shared link view, "# Booking" column is fully displayed, and clicking on the "copy link" button triggers a toats. - Adds the possibility to group reminders given the appointment_type. - Displays appointment type tags (10 max) in reminders kanban view. - When creating an appointment in the gantt view from the slots, the range stays highlighted instead of disappearing right away. --- Task-6293537
This update aligns several localization and tax modules with recent platform changes to address handling and portal dependencies. It helps keep checkout, portal address forms, and tax-related integrations working consistently after underlying community updates.
Original PR description
This commit adapt community changes: - Adapt zip_required reference to zip_applicability. - Adapt dependancy of localizasion modules as we merged portal_address_extended into portal and made portal dependant on base_address_extended. - Adapt address page overrides. task-5208254
Odoo views can now define their preferred dialog width directly, making pop-up windows more consistent across features such as quick creation, search, and embedded forms. This reduces reliance on action-specific settings and should make future interface behavior easier to standardize.
Original PR description
This commit adds the support for the `dialog_size` attribute on the root node of views' archs. When the view is rendered inside a dialog, e.g. action in target="new", many2one "search more"/"create and edit", x2many FormViewDialog...), this attribute is used to determine the size (width) of the dialog. Possible values are those of dialog.js: "sm", "md", "lg", "xl", "fs" or "fullscreen". Before this commit, it was only possible to specify the dialog's size for actions with target="new", by setting the `dialog_size` key in the context. The plan is to convert the usecases to use this new API. Task~6429925
Technicians can now open documents linked to equipment directly from the shift form. This makes technical documentation easier to access on site, helping teams diagnose and resolve service issues faster.
Original PR description
This commit adds a "Documents" stat button on the shift form that opens the documents linked to the equipment (serial numbers) selected on the shift. This lets technicians access technical documentation for the equipment directly from the shift while on site, helping them diagnose and resolve issues more efficiently. task-6090002
This update adds a VAT reconciliation check to help users review tax report grids more easily. It helps identify potential reporting mistakes, such as using the wrong tax grid or account, reducing the risk of inaccurate tax filings.
The notebook tab styling in Odoo Enterprise has been adjusted so tab labels no longer appear bold. This creates a lighter, more consistent interface and improves visual alignment with the wider application design.
Original PR description
COM: https://github.com/odoo/odoo/pull/286774 task-6527644
Reconciled bank statement lines now show the account name when the original move name is just a placeholder slash. This makes accounting records easier to read and reduces confusion during reconciliation review.
Original PR description
This commit will treat move with "/" as their name as empty, and put the name of the account in the reconciled line name task-6424612 Forward-Port-Of: odoo/enterprise#127842
Website owners can now configure the header search bar, including what it searches, sorting, and autocomplete suggestions, making site-wide search more relevant to each website. Product searches also return items from matching categories, helping shoppers find purchasable products faster instead of only seeing category links.
Original PR description
## [REF] html_builder, website_sale: let plugins declare dirty trackers Commit f3c119dd034b removed the `savable_selectors` resource from `SavePlugin`, on the grounds that `.o_savable` already…
## [REF] html_builder, website_sale: let plugins declare dirty trackers Commit f3c119dd034b removed the `savable_selectors` resource from `SavePlugin`, on the grounds that `.o_savable` already identifies the elements to flag with `o_dirty` and carries checks a raw selector bypasses, and adapted the `website_blog` templates so that the elements that needed saving qualify for the class instead of being named by a selector. That reasoning holds for every element that can qualify. It does not hold for an element rendered from template parameters. Such an element has no arch to be written back to, so it can never be `.o_savable`, and a plugin that needs to know when it changed is left duplicating the whole mutation resolution to look for its own selector. Commit 728049b4597b did this for the products grid of the shop, so the resolution exists in two places, and every further element in that situation duplicates it again. This commit replaces the hardcoded pair in `handleMutations` with a `dirty_trackers` resource, of which `SavePlugin` registers the existing `.o_savable` / `o_dirty` entry, and migrates the products design panel, which resolved mutations itself, to declare a tracker instead. The wishlist table, whose selector the products design panel used to resolve on its behalf, now declares its own next to its `product_design_list_to_save` entry. The arch saving pipeline is untouched, and the products design panel now honours `ignoreDirty` during drag and drop, which its own copy did not. Unlike the removed resource, a tracker does not widen what can be saved. It names its own class, which no `dirty_els_providers` returns, so the element never reaches the arch saving pipeline. What is being extended is change notification, not savability. A tracker matches the closest ancestor of the mutated element by default, which is what an element mutated through its descendants needs. The products grid and the wishlist table read what they persist from their own attributes, and the grid holds inline-editable product names, so `closest` would mark it dirty on every keystroke inside a tile. They declare `match: "self"` instead, which also keeps the constant-time check they had before. ## [IMP] website*: allow configuring the header search bar The Search snippet exposes builder options for what it searches within, how results are sorted, and how many autocomplete suggestions it shows. The search bar `website.header_search_box` renders has none of them. Its scope, results page and suggestion count are hardcoded, and clicking it in the editor selects nothing at all. A website dedicated to a single purpose therefore cannot point its site-wide search at that content. This commit registers the same searchbar option on the header search bar and stores its settings on the website record instead of the view arch. The option mutates the DOM as a live preview, and a plugin resolves those mutations itself and writes the values back to the record on save. The bar is also marked `o_no_save`, as saving it as a custom snippet would produce a block whose configuration lives outside its own markup. Searchable scopes were declared in two places, their label and results page in each module's builder template and their models in `_search_get_details`. They now come from `website._get_search_scopes()`, which `website.get_search_scopes()` exposes to the builder. This removes the per-module option templates. Setting the suggestion count to 0 now disables the autocomplete instead of falling back to 6, and the `limit` and `order_by` defaults move into `website.website_search_box_input` so that callers pass plain values. ## [IMP] website_sale: return a category's products when searching it `product.public.category` is searched alongside `product.template`, so a term matching a category name returns that category as a result of its own. The products it contains are not returned unless their own fields match the term as well, which they usually do not. Searching "chairs" offers a link to the Chairs category and nothing to buy, and the visitor has to click through to see anything. This commit adds `public_categ_ids.name` to the searched fields of `product.template`, the way the names of its tags and of its attribute values are already searched, so that a product matches when one of its categories does. The categories are also passed along with the tags of the product, so that the category a product was matched on is shown next to it. The highlight handler renders only the entries that matched, so a product found by its own name is left as it was. The tags and the attribute values were mapped to two fields and rendered as two rows of badges stacked on top of each other, which the categories would only have made more noticeable. They are merged into a single `badges` field so that all of them wrap as one row. Related: https://github.com/odoo/enterprise/pull/126373 task-6422203
Duplicating sections with many lines is now much faster and less likely to time out. The change batches the background recalculations needed during duplication, reducing repeated server calls and improving responsiveness for large sales documents.
Original PR description
Issue: Sections containing a large number of subsections or lines can take too long to duplicate and may eventually time out. The slowdown stems from the onchange issues in `_duplicateRecords()` in…
Issue: Sections containing a large number of subsections or lines can take too long to duplicate and may eventually time out. The slowdown stems from the onchange issues in `_duplicateRecords()` in sale.order.line. Each sale.order.line is first created as an empty datapoint, which triggers an onchange RPC. The copied values are then applied, triggering a second onchange RPC for every duplicated line. Fix: Prepare the copied values before creating the datapoints and send them through a batched onchange. This retrieves the required onchange values for all duplicated lines in a single RPC. Benchmarks: sale.order.line onchanges: Note: "Timing Before" is calculated by the difference between the first and last sale.order.line onchange completion times. | Lines | RPCs Before | RPCs After | Timing Before | Timing After | Speedup | | ----: | ----------: | ---------: | ------------: | -----------: | ------: | | 10 | 20 | 1 | 0.31s | 0.04s | 5.52x | | 50 | 50 | 1 | 1.62s | 0.14s | 11.67x | | 100 | 200 | 1 | 3.41s | 0.25s | 13.64x | | 500 | 1000 | 1 | 10.98s | 0.96s | 11.43x | | 1000 | 2000 | 1 | 31.07s | 2.74s | 11.34x | Related: opw-6395475 Forward-Port-Of: odoo/odoo#287031 Forward-Port-Of: odoo/odoo#280418
Improves how Odoo updates related records in large tree-like data sets, avoiding slow full-table scans when moving a branch. This can significantly speed up operations such as stock transfers or partner/location updates for databases with very large volumes of records.
Original PR description
Our customer has 1.7M packages and very slow validate: the transfer took 8.6s, and 5.35s of it was the single `UPDATE` that `_parent_store_update` runs to move `parent_path` over a subtree. It looks…
Our customer has 1.7M packages and very slow validate: the transfer took 8.6s, and 5.35s of it was the single `UPDATE` that `_parent_store_update` runs to move `parent_path` over a subtree.
It looks for the descendants with `LIKE concat(node.parent_path, '%')`. The pattern comes from a column, so Postgres cannot use the index on `parent_path` and scans the whole table. The change asks for the same rows as a range, which the index does serve:
AND child.parent_path >= node.parent_path
AND child.parent_path < left(node.parent_path, -1) || '0'
`parent_path` always ends with `/` and `0` is the next character, so that closes the range on the subtree. Same rows, same order, one line of SQL.
On a table of 302000 rows, moving 62 nodes, both forms return the same 9362 rows: 3302ms before, 223ms after. On the customer database a single parent write went from 0.82s to nothing measurable.
-- before
Update on stock_package child (actual time=3175.525..3175.527)
-> Nested Loop (actual time=7.171..2987.424 rows=9362)
Join Filter: ((child.parent_path)::text ~~ concat(node.parent_path, '%'))
Rows Removed by Join Filter: 18714638
-> Seq Scan on stock_package child (rows=302000)
-> Materialize (rows=62 loops=302000)
Execution Time: 3301.796 ms
-- after
Update on stock_package child (actual time=223.040..223.041)
-> Nested Loop (actual time=7.874..22.389 rows=9362)
-> Index Scan using stock_package_pkey on stock_package node (rows=62)
-> Index Scan using stock_package__parent_path_index on stock_package child
Index Cond: ((parent_path >= node.parent_path) AND (parent_path < left(node.parent_path, -1) || '0'))
Execution Time: 223.041 ms
This is not about only `stock.package`. Every model on `_parent_store` pays it once the table grows, `res.partner` and `stock.location` included.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287180Belgian payroll rules now use an extra hours category instead of the previous overtime category. This keeps payroll terminology and related employee/work-entry setup aligned with the intended business process for tracking additional hours.
Original PR description
Task: 6488016
Moving a document from a folder to My Drive now creates the same activity log entry as moving it to any other folder. This gives users a consistent record of where files have been moved, improving traceability across Documents.
Original PR description
This PR ensures that moving a file from a folder to My Drive creates the same chatter log as other folder move operations. This keeps file movement tracking consistent across all destinations. Task-6391383
VoIP call flows can now continue after playing an audio message, instead of stopping at that step. Users get clearer routing options with separate paths for callers who skip the message and those who listen to the end, while audio timing stays aligned when messages change.
Original PR description
"Play Audio" nodes had no output: the PBX has no "play a sound then continue" primitive of its own, only a Menu (IVR) does, through its timeout branch. Back "Play Audio" with a Menu wrapping the…
"Play Audio" nodes had no output: the PBX has no "play a sound then continue" primitive of its own, only a Menu (IVR) does, through its timeout branch.
Back "Play Audio" with a Menu wrapping the chosen sound instead of the bare sound itself, with one option per key (0-9, *, #) so any key press exits early ("Skip") while letting the message play out reaches "After". The node still shows a plain sound picker and only two outputs: the wrapping Menu is created (or duplicated, since a sound can only ever back one Menu) behind the scenes, stays out of the Menus list, and is bypassed entirely when re-opening the node to edit its sound directly.
Keep the Menu's timeout in sync with its sound's own duration, recomputed whenever the call flow is saved, so a re-recorded or regenerated message is never cut short or left with dead air.
Update the JS unit and Python tests broken by the underlying model change (an audio_message node's record is now a voip.ivr, not a voip.sound, and the node no longer reports `terminal: true`).Knowledge and Appointment website search options are now declared in a shared central place instead of separate page builder templates. This makes search configuration easier to maintain and keeps these modules aligned with the broader website search improvements.
Original PR description
The community counterpart of this commit moves the declaration of the website search scopes out of each module's builder template and into `website._get_search_scopes()`, so that a scope's label, its results page and its models are declared in one place. This commit follows that change for the knowledge and appointment scopes and removes their builder templates. Related: https://github.com/odoo/odoo/pull/279774 task-6422203
This update re-enables a test setting for continuous production scenarios in shop floor work orders. It helps ensure users can complete work orders reliably across more production use cases after a prior limitation was fixed.
Original PR description
During the continuous production cleaning, a limitation was introduced that blocked users from marking a WO as done in shopfloor. This limitation was addressed and fixed in: odoo/enterprise#125787 , so we can safely uncomment the continuous flag to ensure we are covering different usecases in the tests. Forward-Port-Of: odoo/enterprise#128911
Payroll rule parameter lookups now handle elevated access internally instead of requiring each caller to request it. This makes payroll-related calculations and reports more consistent across countries while reducing the risk of access-related errors for HR teams.
Original PR description
Move sudo inside the _get_parameter_from_code instead of calling the method with sudo. task-6518823
Belgian payroll now settles remaining mobility budget amounts at year-end or on an employee's final payslip, aligning calculations with Partena requirements. The update improves accuracy for yearly prorations, termination fees, compliance checks, and warnings for cases such as budgets outside limits or employees combining a mobility budget with a CO2-emitting company car.
Original PR description
Rework the mobility budget logic according to Partena requirements. - Settle the remaining mobility budget in December or on the employee's final monthly payslip instead of in the anniversary month. - Include the mobility budget amount in termination fee computations. - Compute the yearly mobility budget as a prorated amount based on all employee versions within the calendar year. - Add warnings when the mobility budget falls outside the configured boundaries or exceeds 20% of the yearly wage. -Add a dashboard warning for employees with a mobility budget and a company car emitting CO₂. -Move the computation of the default mobility budget amount from l10n_be_hr_contract_salary to l10n_be_hr_payroll. related Upgrade commit: https://github.com/odoo/upgrade/pull/10877 task: 6263962
The web client’s underlying interface library was updated to the latest Owl release. This helps keep Odoo’s web experience current and maintainable, with limited direct impact expected for day-to-day users.
Original PR description
Release notes: https://github.com/odoo/owl/releases/tag/v3.0.0-alpha.49 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#287202
VoIP users can now manage multiple caller ID numbers and have the right personal number selected automatically based on the country they are calling. This helps teams with numbers in multiple countries present a more appropriate caller ID, while still allowing manual selection of shared or pinned numbers when needed.
Original PR description
A user could only ever be assigned a single DID number, which forced Wazo customers with numbers in several countries to always present the same caller ID abroad. Users can now hold several active DIDs; the outbound caller ID is picked automatically based on the destination country (falling back to a persisted choice), and can be reviewed, pinned, or toggled off from the status menu's "My numbers" section. The in-call view shows which number is being used while dialing out.
Belgian payroll now calculates salary reductions for unpaid time using the smaller paid or unpaid portion of the month, with a special rule for an exact 50/50 split. This makes deductions more consistent across months so the cost of an unpaid day is fairer regardless of the calendar.
Original PR description
In order to make salary computation more fair between months (taking an unpaid day off should cost the same from one month to another), we should always count the smallest amount of days and compute…
In order to make salary computation more fair between months (taking an unpaid day off should cost the same from one month to another), we should always count the smallest amount of days and compute salary based on that: If on the month, the employee got more unpaid time than paid time: -> we should take the HOURLY wage (smoothed on trimester) and multiply it by the amount of hours worked on the period. If on the month, the employee got more paid time than unpaid time: -> we should take the HOURLY wage (smoothed on trimester) and multiply it by the amount of hours not worked on the period. Remove that amount to the monthly wage. If on the month, there is a perfect 50% ratio between paid and unpaid, we take the wage / 2 Note: As the hourly wage is smoothed on trimester, the hourly wage is never equal to the normal hourly wage of the current month. Smoothed on trimester = wage * 3 months / 13 weeks / hours_per_weeks Meaning that if you take one unpaid leave in the month, assuming wage = 2200 and number of working days on the month = 22 and hours per week = 38 (5 days a week): you won't earn 21 * 100 = 2100. You will earn instead : 220 - 1 * (2200 * 3 / 13 / 5) = 2200 - 1 * 101.54 = 2098.46 Task-6352246
Administrators can now request a detailed database execution analysis directly from profiled slow queries, avoiding manual copy-paste work and server access. This helps technical teams investigate performance bottlenecks faster while keeping the data model compatible with existing tools and limiting access to admin users.
Original PR description
The profiling feature is really cool to analyse performance issues and detect bottlenecks. However, once you've identified a slow query, there's nothing to help you. You need to: - copy-paste the…
The profiling feature is really cool to analyse performance issues and detect bottlenecks. However, once you've identified a slow query, there's nothing to help you. You need to: - copy-paste the speedscope entry with the SQL query - extract the query from the line - have ssh access to the server - manually run EXPLAIN ANALYSE This commit introduces a way to run EXPLAIN ANALYSE on any profiled query. Design decisions ---------------- We are keeping the current schema, with SQL stored in a serialized blob. This allows external tools (runbot, ...) to work the same way across versions. It also allows to add metrics easily in the blob in stable versions if necessary. Preserving the schema also makes it possible to backport this feature to stable versions in the future, as we could simply extract the feature and move it to a separate module. Upon request, we duplicate the SQL data in a separate model (`ir.profile.query`) so it can be displayed and manipulated with standard list/form views. Duplicating the data is acceptable since it's throwaway data that is regularly garbage-collected. Visualizer? ----------- We considered including dalibo's open-source visualizer (pev2) to be able to visualize plans in one click. However, because that component depends on Vue.js, including it would likely trigger automated vulnerability scanners. Even if it's secure, we want to avoid the overhead of processing false-positive security reports. As a general rule, we also avoid adding external dependencies whenever possible. Instead, users can take the generated execution plan and visualize it as they see fit (e.g., using explain.dalibo.com). (Please note that SQL queries may contain sensitive data!) This feature is obviously limited to admin users. task-6422397 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
Belgian payroll now handles warrants more accurately by separating warrants that are subject to social security from those that are not. This improves payroll calculations and statutory reporting for taxes, social security declarations, and employee certificates.
Original PR description
Previously, the warrants structure only supported entering a raw amount on which a fixed withholding tax rate was applied. Requalified warrants (subject to ONSS) were not considered either. This commit refactors the warrant structure to properly compute ATN, ONSS, and withholding taxes. The single generic input was replaced by two distinct inputs for warrants with and without ONSS, separating the calculation bases. A rule parameter for the default 18% ATN was introduced, and we now compute the Withholding Tax (always) and ONSS (only for requalified warrants) the same way as a bonus. The ATN percentage can be overridden with a salary input, and we can also input a prepaid amount for the withholding tax. The DMFA was updated to report the warrant remuneration and contribution when subject to ONSS. The relevant values were also added to the Social Security Certificate. Besides, we made sure to report the gross and the withholding tax in 281.10/20 and 274.xx reports. Task-6392255
The French simplified profit and loss report now includes all relevant expense lines in the Operating expenses total. This helps companies using the French fiscal declaration avoid understated expense totals and improves accuracy of the 2033 B report.
Original PR description
**Steps to reproduce:** - Install the `l10n_fr_reports` module and switch to the FR Company. - Navigate to Invoicing > Reporting > Fiscal Declaration and select `2033 B`. - Observe the formula of `A…
**Steps to reproduce:** - Install the `l10n_fr_reports` module and switch to the FR Company. - Navigate to Invoicing > Reporting > Fiscal Declaration and select `2033 B`. - Observe the formula of `A - Accounting income` > `Operating expenses (II)`. **Observation:** The formula does not include the balances of `FR_2033_B_c244`, `FR_2033_B_c250`, and `FR_2033_B_c252`. **Root Cause:** At [1], the formula for `Operating expenses (II)` is missing the balances of fields `244, 250, and 252`, even though these lines are part of the operating expenses section. **Fix:** This commit ensures that `Operating expenses (II)` displays the correct total balance. **Reference**: <img width="1422" height="490" alt="6482797" src="https://github.com/user-attachments/assets/95b35ac7-f410-413b-8ef9-29f97f16c35a" /> [1]: https://github.com/odoo/enterprise/blob/54bfcbee37a241ae70b9bebb9cf23d76172e18fe/l10n_fr_reports/data/fiscal_declaration/report_2033_B_simplified_profit_loss.xml#L302 opw-6482797 Forward-Port-Of: odoo/enterprise#129348
This fixes several issues in the time off request process, especially around partial days, hourly requests, timezone handling, and unusual work schedules. Employees and managers should see more accurate dates, durations, and calendar behavior when creating or editing leave requests.
Original PR description
Here is the leaves behavior: Stored field readonly (shouldn't be edited): `date_from/to` -> UTC reference Stored fields editable to request: - time type in days: `request_date_from/to` - time type in…
Here is the leaves behavior: Stored field readonly (shouldn't be edited): `date_from/to` -> UTC reference Stored fields editable to request: - time type in days: `request_date_from/to` - time type in halves: +`request_date_from/to_period`, `request_duration` (multidays/solo) - time type in hours: +`request_hour_from/to` (not in the view) Computed field, (editable for a time type in hours): `request_date_hour_from/to` -> converted to the reader tz It means no more cycle exits: `request_date_hour_from/to` edited => inverse will update requests stored fields => date_from/to will be recomputed based on the request stored fields The purpose of using `request_date_hour_from/to` is to display for the user the same range of hours for employees with different tz Other little fixes around: - _to_utc(): round the hour to the whole minute, where the carry can reach the hour, and stop at the end of the day, as float_to_time takes neither a minute 60 nor an hour 24. - _split_leaves(): both parts are whole where they are cut and carry the request_duration their periods describe, dates included, instead of the half day copied from the original. - _get_hours_for_date(): a day the schedule leaves out borrows the hours of the nearest day it names, not the widest hours of the whole schedule, which no single day of a two week rota works; a schedule naming no hour at all falls back on an average day centred on midday, where it used to leave the request without any extent. - _compute_last_several_days(): a request whose end precedes its start is one being edited, not one of several days, so moving one bound of the pair before the other catches up no longer snaps the duration back onto whole days. task-6459867
The Time Off Gantt views now better reflect the updated fixed leave request process and align dates with each user's local wall-clock time, like calendar views. This helps HR teams and managers see leave schedules more accurately in overview and management screens.
Original PR description
Gantt adapted with the new fixed leave request process Gantt view timezoned based on the wall clock of the user as calendar views now (Overview and Management) task-6459867
Users sending Colombian support documents to DIAN now see a clear message when the required operation mode has not been configured. This replaces a confusing server error with guidance on what is missing and where to fix it, helping businesses complete electronic document submissions faster.
Original PR description
**Steps to reproduce:** * Install `l10n_co_dian`. * Configure a company with the Colombian localization. * Set up a DIAN operation mode for Electronic Invoices only (no Support Documents mode). *…
**Steps to reproduce:** * Install `l10n_co_dian`. * Configure a company with the Colombian localization. * Set up a DIAN operation mode for Electronic Invoices only (no Support Documents mode). * Create a vendor bill marked as a Support Document and click **Send to DIAN**. **Observed behavior:** * A cryptic server error is raised: *"TypeError: unsupported operand type(s) for +: 'int' and 'str'"* * No actionable information is shown to the user. **Cause:** * `_add_document_config_vals` assigns `vals['l10n_co_dian_operation_mode']` via `.filtered()`, which returns an empty recordset when no matching operation mode exists. * Accessing a `Char` field on an empty recordset returns `False` (a `bool`, which is a subclass of `int` in Python). * Concatenating `False` with strings in the `sha384` hash calculation raises the `TypeError`. * The missing-mode guard only existed in the commercial events path, not in the main invoice export path. **Fix:** * Raise a descriptive `UserError` that tells the user which mode is missing and where to configure it. opw-6499321 Forward-Port-Of: odoo/enterprise#130853 Forward-Port-Of: odoo/enterprise#128935
Reconciliation model labels are now applied using the company’s language, so automated and manual reconciliation create journal items with the same wording. This prevents misleading labels when users work in different languages or models are duplicated and edited.
Original PR description
### Problem `label` on `account.reconcile.model.line` is a **translatable** field, but its value is written onto the journal item created when the model is applied (`account.move.line.name`). That…
### Problem
`label` on `account.reconcile.model.line` is a **translatable** field, but its value is
written onto the journal item created when the model is applied (`account.move.line.name`).
That means the label is read in the language of whoever applies the model:
- a user working in another language writes the translated value;
- the auto-reconciliation cron writes the **source** value, since it runs as OdooBot.
So the very same reconcile model ends up writing two different labels on the journal items,
depending on who applied it.
### How it shows up
It becomes visible when a reconcile model is created by **duplicating** an existing one and
the label is then edited while working in a non-source language. The translation holds the
new text, while the source value silently keeps the label of the original model — and the
source value is exactly the one the cron writes. The result is a set of journal items where
some carry the intended label and some carry the label of an unrelated model.
### Fix
The journal item belongs to the company, so the label is read in the **company** language
via a small `_get_aml_label()` helper, instead of the language of the current environment.
It falls back to the current behaviour when the company has no language set.
`_prepare_aml_vals()` is the only place in 18.0 that reads `self.label` for the journal item.
### Test
Adds `TestBankRecWidget.test_auto_reconcile_model_label_uses_company_lang`: a reconcile model
whose line label is translated in the company language, applied by the auto-reconciliation
cron running in the source language, and asserts the journal item carries the company-language
label.
```
odoo -d <db> -u account_accountant --test-enable --stop-after-init \
--test-tags /account_accountant:TestBankRecWidget.test_auto_reconcile_model_label_uses_company_lang
```
Without the fix the test fails with `[{'name': 'Frais bancaires'}] != [{'name': 'Bank fees'}]`;
with the fix it passes. The full `account_accountant` suite was also run on a clean 18.0
database: 203 tests, 0 failed, 0 errors.
Forward-Port-Of: odoo/enterprise#130865
Forward-Port-Of: odoo/enterprise#128433This fix restores correct height settings for website map sections, including simple maps that do not use a Google API key. It also brings back support for using map snippets in page templates with padding, helping website pages display maps as intended.
Original PR description
[Commit ace2431d] modified the way the height of Google maps snippets is computed. On simple map snippets (the one available without a Google API key), the height option didn't work properly or wasn't even available anymore. Additionally, [commit af49dbe8] added support to include the map snippet within a `t-call` on XML templates, together with a `padding` parameter. This was lost and not adapted when the other commit was merged in master. [Commit ace2431d]: https://github.com/odoo/odoo/commit/ace2431ddfdd7e99cf13e9a8458a109e92dd1a6a [commit af49dbe8]: https://github.com/odoo/odoo/commit/af49dbe8ccfbd6b31c899ea7699dff38d178ad4b task-6503185
Fixed an issue that caused an error when employee cashiers performed Cash In/Out operations in Point of Sale. The cash movement now records the employee correctly, helping stores continue cashier workflows without interruptions.
Original PR description
Steps to reproduce: -- - Enable Employee Login in PoS. - Log in as an employee cashier. - Perform a Cash In/Out move. - Error! Issue: -- An error occurs when making a cash move while logged in as an employee cashier. Cause: -- The cash move request array passed employee information in place of the partner ID, resulting in a database type error. Fix: -- Passed the employee ID as a separate parameter in the cash move payload, and updated the backend session to save the employee ID on the cash move record. Task- 6445993
Product identifiers sent to Google Analytics now match the identifiers used in Google Merchant Center feeds. This helps Google Ads connect Shopping ad clicks with purchases more reliably, reducing attribution mismatch warnings.
Original PR description
**Issue:** When google analytics (GA) and google merchant center (GMC) are setup, Google Ads diagonistic reports that item IDs cannot be matched to Merchant Center. **Why this happens:** `_get_google_analytics_data` sets `product.barcode or product.id` for `item_id`, while `product.feed._prepare_gmc_items` defaults to `product.default_code or product.id` for the feed's `id` field. Google Ads/Analytics attribution relies on GA4's `item_id` matching GMC's `id` for the same product to connect Shopping ad clicks to purchase events. **References:** https://support.google.com/merchants/answer/6324405?sjid=15224664355638221483-NC https://support.google.com/google-ads/answer/14943675?hl=en opw-6443326 Forward-Port-Of: odoo/odoo#287074 Forward-Port-Of: odoo/odoo#285010
This fix makes the website builder correctly remember changes to form field default values, so undo actions restore the page as expected. It also prevents stale values from remaining when switching date fields to date-and-time fields, improving editing reliability for website forms and translations.
Original PR description
The `value` property of the elements is not tracked by the history plugin, because `MutationObserver` does not produce mutations for that. This commit uses custom mutations when the `value` is changed, to restore the previous value on undo. Steps to reproduce: - Open website builder - Add a form - Set a "Default Value" on a text field - Press enter (to end preview) - Undo (with the button, or with focus out of the option's input) - Bug: The value shown in the page did not revert with undo Similar bug in translate mode task-6229671 Forward-Port-Of: odoo/odoo#287325 Forward-Port-Of: odoo/odoo#281232
The Indian GSTR POS report tests were updated to reflect that point-of-sale session closing entries now use a dedicated closing journal. This keeps report validation aligned with the current accounting flow and helps prevent false test failures.
Original PR description
Following the introduction of a dedicated closing journal in point_of_sale, session closing entries are posted in the POSC journal rather than sharing the Orders/Invoicing journal sequence. task-id: 6446274
The Stock Delivery module will once again install automatically when both Sales Stock and Delivery are installed. This prevents businesses from missing delivery-related stock functionality after recent dependency changes.
Original PR description
The `printer` module was added to dependencies of the `stock_delivery` module. Due to that, now if `sale_stock` and `delivery` are installed, this module is not being installed automatically. This commit makes sure this module is installed if these two modules are present. task-6469674 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
Secondary badges are now easier to read in both light and dark display modes. This improves visual clarity for users by ensuring badge text and backgrounds have enough contrast.
Original PR description
Before this PR:- ========================== Secondary badges are barely visible in light and dark modes. <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/552dd924-4ab4-4fd5-b0fe-b103697a0bb9" /> <img width="500" height="200" alt="image" src="https://github.com/user-attachments/assets/a199ad73-bd94-42dd-aa46-1fc7fb2f9436" /> After this PR:- ========================== Make the badge text and background clearly visible in both modes. <img width="1232" height="672" alt="image" src="https://github.com/user-attachments/assets/cbff2756-f2e4-42fa-97c6-669409fd4efb" />
Fixed an issue that prevented manufacturing orders from being created on small screens when work orders and operation instructions were enabled. The change ensures the related work order keeps its operation details, so required quality checks are created as expected.
Original PR description
Steps to reproduce --- 1. Enable Work Orders. 2. On a product's BoM, add an operation carrying an Instructions step. 3. On a small screen, create a manufacturing order for that product, set the…
Steps to reproduce --- 1. Enable Work Orders. 2. On a product's BoM, add an operation carrying an Instructions step. 3. On a small screen, create a manufacturing order for that product, set the product and save. Expected: the MO is saved and the generated work order carries its BoM operation. Actual: saving raises `Missing required field 'Product' (product_id) for model 'Stock Move'`, and once that is bypassed the generated work order has no operation, so its `quality_point_ids` stays empty and no `quality.check` is created. Issue --- On a small screen the MO form resolves its x2many relations to their kanban sub-views, so the fields carried in the onchange and save payloads are only those the active sub-view declares; two relations lose data this way. `move_finished_ids` is an invisible relation that always holds the product's finished move, built on the draft by `_compute_move_finished_ids` through `_get_moves_finished_values` with `product_id` and `product_uom_qty` set. https://github.com/odoo/odoo/blob/c9012f5ae48e29ff49391b722ed798237c448805/addons/mrp/models/mrp_production.py#L1354-L1371 https://github.com/odoo-dev/odoo/commit/c9012f5ae48e29ff49391b722ed798237c448805 gave that field `mode="list,kanban"` while only a `<list>` sub-view is defined for it. https://github.com/odoo/odoo/blob/c9012f5ae48e29ff49391b722ed798237c448805/addons/mrp/views/mrp_production_views.xml#L405-L410 On a small screen the field resolves to kanban mode, but since no kanban sub-view exists its field spec comes out empty, so on the first save the client sends the finished move as an empty create and the `stock.move.product_id` NOT NULL constraint aborts the whole save, so no MO can be created on mobile. The field is invisible and never rendered, so it has no use for a kanban view in the first place; dropping the kanban mode keeps it on its list spec, which carries `product_id`, on every screen size, while the visible Components and By-Products lists are unaffected because they resolve a populated kanban sub-view. The `workorder_ids` kanban sub-view must likewise carry `operation_id`, or the generated work order is saved without an operation and its `quality_point_ids` stays empty, so no `quality.check` is created. https://github.com/odoo-dev/odoo/commit/e3f6cef5cf94391b5c018c5eb44ce1ddee99290b had restored the invisible `operation_id` on that kanban and https://github.com/odoo-dev/odoo/commit/6318895101435a0a9d4bdff0b8dbfbb17179378e dropped it again in a kanban rework, so it is restored. opw-6488529 X-original-commit: https://github.com/odoo-dev/odoo/commit/af70218f325147a51ca6e46f4827d697c7ed7801
Status indicators in kanban cards now keep a consistent size across Event, Maintenance, and Project views. This prevents cards from subtly changing height when their status changes and makes warning indicators clearer.
Original PR description
*: event, maintenance, project, web __Problem__ In kanban views, the status bubble has two issues: - The exclamation mark of `error` is too slim. - An icon and an `o_status` bullet don't take the same room: `font-size` alone doesn't constrain the glyph height exactly, so a kanban card grew or shrank slightly depending on which state it was in. __Fix__ Render the state as an `o_status` circle carrying a `priority_high` icon, scaled down to fit inside the bullet, and cap the icon with `max-height` so every state occupies the same height. Moved some SCSS rules in `web` so `event` to remove duplicate code in the other modules. task-6377407
Fixed an issue where code editor fields could cause invoice forms to crash when document extraction features were installed. The change keeps field detection accurate without changing how the editor looks or behaves.
Original PR description
Fix for #286871. opw-6543997 ### The problem `web.AceField` and `web.IrUIViewAceField` render their root div with the `o_field_widget` class, but the `Field` wrapper already puts that class on the…
Fix for #286871.
opw-6543997
### The problem
`web.AceField` and `web.IrUIViewAceField` render their root div with the
`o_field_widget` class, but the `Field` wrapper already puts that class on the
div it renders, along with the `name` attribute. Every ace field therefore
renders a nested `o_field_widget` with no name:
```html
<div name="my_field" class="o_field_widget o_field_code ...">
<div class="o_field_widget oe_form_field o_ace_view_editor oe_ace_open">
<div class="ace_editor">... <textarea class="ace_text-input">
```
Any code that goes up from a DOM node with `closest(".o_field_widget")` to find
which field was clicked stops on the inner div, finds no `name` and cannot
resolve the field.
`iap_extract` does exactly that, in a `focusin` listener on `window`, and
`account_invoice_extract` installs its renderer for `account_move_form` with
`force: true` — so it runs on every invoice form. With no name on the inner div
it builds `"<parent_field>.null"`, and since the name now contains a dot,
`getBoxType` takes the x2many branch:
```js
modelFieldType = this.props.record.data[parentField]?._config.fields[fieldName]?.type;
```
For a `widget="code"` field, `record.data[parentField]` is a plain string. It is
truthy, so the optional chaining does not short-circuit, but it has no
`_config` → `undefined.fields` → `TypeError: Cannot read properties of
undefined (reading 'fields')`, and the whole form breaks.
### Steps to reproduce
1. Install `account_invoice_extract`.
2. Put a `widget="code"` field on the `account.move` form view (with
`l10n_ar_edi` installed there are already two on the ARCA tab).
3. Give the field a value — with an empty value the error does not happen.
4. Enable developer mode and click inside the code editor.
Reproduced on a plain 19.0 runbot build.
### The fix
Drop `o_field_widget` from the root div of both ace templates, since the
wrapper already provides it. The only rule that relied on both classes being on
the same element was `.o_field_widget { &.o_ace_view_editor { ... } }` in
`fields.scss`; it becomes a descendant selector, so the rendering is unchanged.
`account_invoice_extract` / `iap_extract` could be made more defensive as well
(`?._config?.fields[...]`, or not building a `parent.child` name when the
closest `.o_field_widget` has no `name`), but that lives in enterprise and the
duplicated class looks like the actual root cause.Delivery carrier rate checks are now handled more reliably when the shipping selection window opens. This prevents DHL, FedEx, and Envia delivery workflows from failing during automated checks, helping keep shipping cost selection stable for users.
Original PR description
* - delivery_fedex_rest The delivery rate calculation now happens when `choose.delivery.carrier` wizard gets opened (see https://github.com/odoo/odoo/pull/269131). Due to that, some tests fail upon rate calculation. This commit makes sure that delivery rate is not being calculated when wizard is created. task-6276527
Depreciation models that are already linked to assets can no longer be deleted accidentally. This prevents assets from losing required setup information and becoming impossible to reset, cancel, or manage.
Original PR description
**Steps to reproduce:** * Install the **Accounting** (`account`). * Create a **Depreciation Model** (e.g. Linear, 5 years). * Create an asset, assign the depreciation model, and confirm it. * Go to…
**Steps to reproduce:** * Install the **Accounting** (`account`). * Create a **Depreciation Model** (e.g. Linear, 5 years). * Create an asset, assign the depreciation model, and confirm it. * Go to **Accounting → Configuration → Depreciation Models** and delete the model used by the running asset. * Try to **Reset to Draft** on **asset**. **Observed behavior:** * The depreciation model is deleted silently. * The asset's `model_id` FK becomes `NULL`, causing all related fields (`method`, `method_number`, `method_period`, `journal_id`, etc.) to become empty. * Any subsequent attempt to cancel, reset to draft, or delete the asset fails with a **missing required field** error, leaving the asset permanently unmanageable. **Cause:** * `account.depreciation.model` had no `@api.ondelete` guard — deletion was entirely unprotected, unlike `write()` which already blocks edits on models used by running assets. * `model_id` on `account.asset` had no `ondelete` constraint, so the database silently NULLed the FK on model deletion. **Fix:** * Add an `ondelete='restrict',` on a asset's `model_id` field to prevent deletion of a depreciation model that is in use by any asset. opw-6233210 Forward-Port-Of: odoo/enterprise#130859 Forward-Port-Of: odoo/enterprise#126979
French point-of-sale sales that encounter missing e-invoicing data will now download a standard invoice instead of an incorrect pro-forma invoice. This keeps the sale flow consistent while avoiding confusion for customers and staff; failed electronic transmission is not sent externally until the data issue is resolved.
Original PR description
## Steps to reproduce: - Create a customer with France E-Invoicing (UBL2.1) as eInvoice format in a French company - Go to the PoS, select that partner - Make a sale and ask for an invoice - The…
## Steps to reproduce: - Create a customer with France E-Invoicing (UBL2.1) as eInvoice format in a French company - Go to the PoS, select that partner - Make a sale and ask for an invoice - The downloaded invoice will be a pro-forma invoice ## Why the fix: The pro-forma should not be used here, it is because it is used as a fallback when we get an error while trying to print the invoice. https://github.com/odoo/odoo/blob/4a508586970e44367bbdbbb3cbe88ffb5a1eadb7/addons/account/models/account_move.py#L6187-L6204 As we get an error while trying to send the data with this setup, it goes to the fallback and prints a pro-forma invoice, even though this should not be the case, a regular invoice would do. This happens because when an error is found, we do not populate invoice_pdf_report_id, so it goes to the fallback. We now check if there are any errors in the order, and if there are and the customer requests an ubl_21_fr invoice, we just print the invoice as it is, without going to the pro-forma fallback, as this is not the intended flow. With this fix, we now have the same flow as we do in the sales module, that allows the sale even if the customer has missing data. It will just print the invoice and allow the sale but won't send anything to external entities. opw-6428369 Forward-Port-Of: odoo/odoo#286644 Forward-Port-Of: odoo/odoo#281420
Cancelled retail orders and order lines are now saved and marked correctly when sent to Fiskaly. This helps German point-of-sale certifications reflect cancellations accurately, reducing compliance and reporting issues.
Original PR description
In this commit: --------------- - We now store cancelled retail orders on the server and send the `storno` flag as `true` for cancelled lines and orders to ensure proper handling in Fiskaly. task: 6326042 Relataed PR: https://github.com/odoo/odoo/pull/277648 Forward-Port-Of: odoo/enterprise#130751 Forward-Port-Of: odoo/enterprise#120410
This fixes an issue where a measure defined by a report could disappear from the Measures menu after users deselected it and refreshed or filtered the pivot view. Business users can now reliably adjust filters and still find the original reporting options when they need them again.
Original PR description
TL;DR - we lose the measures from arch after a reload, if removed from activeMeasures Step to reproduce: - install pos, create few orders - go to reporting> orders> switch to pivot view - click the…
TL;DR - we lose the measures from arch after a reload, if removed from activeMeasures Step to reproduce: - install pos, create few orders - go to reporting> orders> switch to pivot view - click the `Measures` dropdown, `Order` is already selected - untick it, then apply some filter so that view reloads (ex order date) - reopen `Measures` dropdown, notice `Order` is missing form measures Cause: - view `view_report_pos_order_pivot` has `<field name="order_id" type="measure"/>` in its pivot view https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/point_of_sale/views/pos_order_report_view.xml#L10 - `order_id` is M2O field - Measure is compute from present `activeMeasure` and fields of type `["integer", "float", "monetary"]` https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/utils.js#L89-L120 - when the view is first loaded, `activeMeasure` all the fields with `type="measure"` which is directly passed to pivot's model as a metadata https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/pivot/pivot_arch_parser.js#L59-L60 https://github.com/odoo/odoo/blob/f5c68cf0eb2ce6ec96dd4006b28466044af10e33/addons/web/static/src/views/pivot/pivot_view.js#L41 - when we toggled the `order_id` from measure and reloaded, `order_id` is popped from `activeMeasure` and as it's field type is `many2one` it is not considered for `measures` in `computeReportMeasures` Fix: - maintain the measures from arch separately and feed it to `computeReportMeasures` opw-6416196 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286013 Forward-Port-Of: odoo/odoo#278850
Fixed an issue that prevented invoices for Saudi Arabian customers from being printed when a tax identification number was present. This ensures Saudi e-invoicing users can print confirmed invoices without encountering an error.
Original PR description
Printing an invoice for a Saudi partner raises an error. Steps to reproduce the error: - Install ``l10n_sa_edi`` module with demo data - Switch to My Saudi Arabia Company - Create a new Partner A >…
Printing an invoice for a Saudi partner raises an error. Steps to reproduce the error: - Install ``l10n_sa_edi`` module with demo data - Switch to My Saudi Arabia Company - Create a new Partner A > Country: Saudi Arabia > VAT Number: 311111111111113 > Click on + Button > Click Tax Identification Number > Save - Create a new invoice > Customer: Partner A > Add a product > Confirm > Print the invoice Traceback: ```py AttributeError: 'account.edi.xml.ubl_21.zatca' object has no attribute '_l10n_sa_get_tin_from_vat' ``` https://github.com/odoo/odoo/blob/2e2054d4203f6453fb35ec6037cda0e2e9033cc3/addons/l10n_sa_edi/models/zatca_ubl_mixin.py#L154-L156 In [Commit], ``_l10n_sa_get_tin_from_vat()`` method is called on self to retrieve ``identification_number``. however, self is an ``account.edi.xml.ubl_21.zatca`` record, while ``_l10n_sa_get_tin_from_vat()`` is a method of ``res.partner``. So, It will lead to the above traceback when printing the invoice. Solution: Call the ``_l10n_sa_get_tin_from_vat()`` method on the partner record instead of self. [Commit]: https://github.com/odoo/odoo/commit/227f61e2cb8582d0c3269bb0ae7256250563847a sentry-7717905761 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287173
This update makes Odoo's PDF handling work consistently with the PDF library version shipped on Ubuntu Jammy, the main supported platform for Odoo 17. It also keeps compatibility with newer library versions, reducing the risk of PDF-related errors across deployments.
Original PR description
Align pypdf usage with the PyPDF2 1.26 API used on Ubuntu Jammy, Odoo 17.0's main supported Ubuntu version, and add the missing compatibility mapping for newer pypdf versions. Forward-Port-Of: odoo/enterprise#130971
This fix makes the Sign module's automated tests work consistently with different supported PDF library versions. It helps prevent false test failures during upgrades or deployments, improving release reliability without changing user-facing signing features.
Original PR description
Prior to this commit, `PageObject` was not re-exported by `odoo.tools.pdf`, forcing tests (such as `test_origin_offset_translation` in `sign`) to patch internal module paths like `PyPDF2._page.PageObject`. This resulted in test failures depending on the installed PDF library version: - `pypdf` (>= 3.0.0): `PyPDF2` submodules no longer exist. - `PyPDF2` 1.x: `PageObject` resides in `PyPDF2.pdf` rather than `PyPDF2._page`. To resolve this: - `PageObject` has been re-exported through `odoo.tools.pdf`. - Update `test_origin_offset_translation` to import `PageObject` via `odoo.tools.pdf` and use `patch.object` with standard attribute names (`cropbox`, `add_transformation`). runbot-946795 Forward-Port-Of: odoo/enterprise#130878 Forward-Port-Of: odoo/enterprise#130017
This fixes the layout of quick create forms in kanban views so field labels appear above their fields again on desktop screens. The change improves readability and restores the expected form appearance when users quickly add new records, such as tasks in Project.
Original PR description
Since odoo/odoo@9fa0bae3d8de3e129836e73623f7112a41ac1a98, the single column layout of form views is driven only by a `media-breakpoint-down(md)` rule. The kanban quick create is a narrow container…
Since odoo/odoo@9fa0bae3d8de3e129836e73623f7112a41ac1a98, the single column layout of form views is driven only by a `media-breakpoint-down(md)` rule. The kanban quick create is a narrow container whatever the viewport, so from `md` up it fell back to the desktop two columns layout and rendered each label on the left of its field instead of above it. Scope the broken table layout to `o_kanban_quick_create_form` itself instead of to the viewport, so the quick create gets the whole `form-break-table` mixin (single column, cell max-width, field widths, input dropdown width) and not only the column count. This mirrors the `:not(.o_kanban_quick_create_form)` exclusion already used a few rules above. The quick create instantiates the form renderer directly, so `o_form_editable` lands on the same element as `o_form_view`, hence the `&.o_form_editable` compound selector. Steps to reproduce: * Go to "Project" * Select any project * Click on "New" => Bug the label is not above the field task-6501365 Code made by Claude Supervised by Romeo Fragomeli (rfr) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now download files opened in the file viewer from Discuss channels without seeing an error. This restores the expected download behavior by using the request type accepted by those file links, while preserving correct downloaded filenames.
Original PR description
Description of the issue/feature this PR addresses: Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel. I've…
Description of the issue/feature this PR addresses:
Downloading an attachment from the file viewer fails with a `405 Method Not Allowed` error when the attachment belongs to a Discuss channel.
I've already submitted a ticket to Odoo: #6430586
Steps to reproduce (on a 18.0 runbot):
1. open Discuss and send an image in a channel
2. click the image to open the file viewer
3. click the download button (either the one in the header or the one in the bottom
toolbar)
The server rejects the request:
```
POST /discuss/channel/1/image/519861?filename=image.png&unique=32647b0f&download=true 405
```
and the user gets a `RPC_ERROR: Arbitrary Uncaught Python Exception` dialog reporting `405 Method Not Allowed`.
Cause: `download()` always issues a POST request, while the routes serving the attachments of a discuss channel only allow GET:
* `/discuss/channel/<int:channel_id>/attachment/<int:attachment_id>`
* `/discuss/channel/<int:channel_id>/image/<int:attachment_id>`
so the request never reaches the controller. Downloading the very same attachment from the attachment card in the conversation still works, because that one is a plain anchor navigation (GET).
This is a regression from fb152985f4b8 ("[FIX] web: download FileViewer files via blob helper"), which routed the file viewer download through `download()` in order to honor the filename sent by the server in the `Content-Disposition` header.
Only 18.0 is affected: saas-18.1 and saas-18.2 do not have the commit that introduced the regression, and from saas-18.3 on, the `urlRoute` override was dropped and channel attachments are served through the standard `/web/content` and /web/image` routes, which are not restricted to GET.
The download is still sent with POST on those branches though, hence forward-porting this up to master.
Current behavior before PR:
Downloading a Discuss channel attachment from the file viewer raises a 405 error and the file is not downloaded. Images and other file types are equally affected.
Desired behavior after PR is merged:
The file is downloaded, keeping the filename advertised by the server. The download is performed with a GET request through `downloadFile()`, which still goes through the blob helper, so the fix of fb152985f4b8 is preserved. This is already the way a file is downloaded from its url in `readonly_file.js`.
Added a test that downloads an image attachment of a channel from the file viewer and asserts the request is a GET on the channel attachment route. It fails before this fix with `POST /discuss/channel/1/image/1`.
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287172
Forward-Port-Of: odoo/odoo#279232Corrected formatting in the Mail and Taiwan EDI ECPay app descriptions so they display properly on the Apps page. This prevents rendering errors and avoids showing raw technical text to users.
Original PR description
Two module manifests hold a `description` whose reStructuredText does not parse. Both are rendered by `ir.module.module._get_desc` (these modules have no `static/description/index.html`, so the RST…
Two module manifests hold a `description` whose reStructuredText does not parse. Both are rendered by `ir.module.module._get_desc` (these modules have no `static/description/index.html`, so the RST path is the one used on the Apps page). ### `mail` The line introducing the list of email-enabled documents is followed by a row of dashes. In reStructuredText an underline directly below a line of text makes it a section title, so docutils treats a 102-character sentence as a heading, then fails on the indented list that follows without a blank line: ``` <string>:38: (ERROR/3) Unexpected indentation. <string>:43: (WARNING/2) Block quote ends without a blank line; unexpected unindent. ``` These are logged every time the description is rendered, and the bullet list ends up rendered as a block quote instead of a list. The dashes are dropped, since the line is a regular sentence and not a section title, and the list is surrounded by blank lines. ### `l10n_tw_edi_ecpay` The whole description is indented, which makes reStructuredText read it as a block quote. A section title is not allowed inside a block quote: ``` <string>:3: (SEVERE/4) Unexpected section title. ``` At SEVERE level this reaches the default `halt_level`, so rendering raises instead of returning a document and `_get_desc` falls back to showing the raw description in a `<pre>` block. The indentation is removed. --- Checked by rendering the `description` of every manifest under `addons/` and `odoo/addons/` with the same docutils settings `_get_desc` uses: these were the only two that reported anything, and both are clean after the change. Forward-Port-Of: odoo/odoo#285323 Forward-Port-Of: odoo/odoo#284360
Preparation receipts in Point of Sale now display whole-number item quantities without unnecessary decimal places when printed through self-ordering devices. This makes kitchen and preparation tickets clearer and reduces potential confusion for staff.
Original PR description
Fix issue where integer qty were displayed as float in preparation receipt when printed through obox (self order). task-id: 6545678 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287201
This fix ensures the editor's color picker can correctly identify the solid color tab regardless of the user's language. It prevents translated labels from causing incorrect behavior, making color selection more reliable for multilingual users.
Original PR description
### Purpose of this PR: - The color picker tabs are registered with a translated name (`_t(Solid)`), and the tab button renders that name as its only content. ColorUIPlugin read the active button's `innerHTML` and compared it to the literal string Solid to know whether the solid tab was the one in use. - Rely on the `solid-tab` class instead, which is built from the untranslated tab id. task-6441654 Forward-Port-Of: odoo/odoo#279941
This update corrects how Romanian electronic invoice attachments are read, preventing errors caused by treating stored file data as text. It helps ensure Romanian EDI invoice processing continues reliably and includes test updates to confirm the behavior.
Original PR description
A previous commit (https://github.com/odoo/odoo/commit/41fe2ebdb9cc37341362d7af829c087a5f72f9f1) added an `encode` call to a line fetching the raw attachment. This assumes the attachment value is a `str`. However, the raw attachment values are actually `bytes` objects. This PR removes the `encode` call and adjusts the tests to reflect the change. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286480
Address details from MapBox location lookups are now matched by their actual labels instead of relying on a fixed order. This prevents incorrect or failed address creation when MapBox returns missing or reordered fields, improving reliability for users who depend on map-based address entry.
Original PR description
The reverse-geocoding call to MapBox asked for five types of information (street, city, postcode, region, country) and read them back from the response by fixed position in the array. MapBox doesn't always return every requested type, or in the same order; if one is missing, every field after it shifts by one position, so the address ended up built from the wrong data, or the code crashed reading a feature that wasn't there. Each field is now looked up by its own type tag instead of its position in the array, so it's matched correctly regardless of order, and a genuinely missing type just resolves to nothing instead of corrupting the rest of the address. task-6542378 Forward-Port-Of: odoo/enterprise#130662
Website building blocks now display more reliably when dark color palettes are selected. This improves readability for previews and placed content such as countdowns, event cards, social icons, and card overlays, while also making snippet previews faster to load.
Original PR description
Fix some snippets in dark palettes task-6485048 Forward-Port-Of: odoo/odoo#284455
This update fixes a spelling error in the Helpdesk Auto Assignment group name. It improves clarity for users and administrators without changing functionality.
Original PR description
This commit fixes the typo in the "Auto Assignment" group. task-6542450 Forward-Port-Of: odoo/enterprise#130880 Forward-Port-Of: odoo/enterprise#130841
Helpdesk users can now create tickets for teams with automatic assignment without being stopped by a Time Off access error. The system still checks who is unavailable before assigning tickets, but it performs that check with the proper internal permissions.
Original PR description
Before this commit, a helpdesk user creating a ticket on a team that assigns tickets automatically got "You are not allowed to access 'Time Off' (hr.leave) records". This happens because picking the next assignee reads hr.leave as the acting user, to skip the members who are off, and a plain helpdesk user has no access to Time Off. This commit reads the employees of the members and their leaves in sudo, as whom to assign is a system decision. https://runbot.odoo.com/odoo/error/947053 Forward-Port-Of: odoo/enterprise#130796
Belgian payroll can now calculate reimbursements for employees who combine a company car with public transport or bicycle commuting. This fixes an issue where selecting a company car erased other transport choices, leading to incomplete payslip reimbursements.
Original PR description
When configuring transport modes on an employee contract version profile, selecting a company car automatically reset public transport (bus, tram, metro) kilometers to zero and disabled the bicycle option. This prevented employees who use multiple transport modes (e.g., combining a company car with public transport or a company bicycle) from having multiple transportation reimbursements calculated on their payslip. Remove the automatic field resets for public transport and bicycle options in `_onchange_transport_mode` and remove `_onchange_has_bicycle`, allowing these transport modes to co-exist with a company car. task-6514557 Forward-Port-Of: odoo/enterprise#130487 Forward-Port-Of: odoo/enterprise#129972
This fixes an issue where quickly typing and pressing Enter while creating a subtask could cause the page to show an error. The change makes the input handling more resilient when the field disappears during a save, improving reliability for users working quickly.
Original PR description
Fast Enter+type could unmount the input mid-await, leaving getEl() null while onChange still read .value directly, throwing a TypeError. Add the same null-check pattern already used in commitChanges. Steps to reproduce: 1. Go to a project and open a task in form view. 2. Create a subtask, type quickly, and press Enter immediately. 3. Repeat until the error occurs. Task-6428344 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The point-of-sale self-order experience now includes a missing compatibility fix needed during carousel transitions. This prevents an error that could occur when a carousel is closed mid-transition, improving reliability for customers using self-ordering.
Original PR description
Due to the `executeAfterTransition` fix not being included in the self order assets, a traceback would occur when the carousel component was disposed during a transition. This commit fixes the issue by including the fix file in the manifest, however some guards needed to be added due to self order not including some of the bootstrap assets. runbot-946931 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Dialog windows no longer show view switching or embedded action controls that cannot work correctly in that context. This prevents users from clicking options that appear available but do nothing or affect the background screen instead of the dialog.
Original PR description
Two elements of the control panel navigate in the current action, which isn't the action of the dialog when the action is displayed in one (target="new"), so they can't work there: - The view…
Two elements of the control panel navigate in the current action, which isn't the action of the dialog when the action is displayed in one (target="new"), so they can't work there: - The view switcher: switchView ignores all calls as soon as a dialog is open. This was done in commit [1] to fix a crash, but the switcher itself kept being displayed, so an action in target="new" with several multi record views (e.g. voip.cloud_storage_error_apps_action) displayed a view switcher that did nothing. - The embedded actions panel (added in [2]): selecting an embedded action calls doActionButton with stackPosition="replaceCurrentAction", which would replace the action in background while the dialog stays open. No action in the standard code is in that situation, so this one was only latent. The view switcher entries and the embedded actions are now both left empty for an action in target="new", which removes the switcher buttons, their small screen dropdown, the corresponding commands of the command palette and the embedded actions panel at once. [1]: https://github.com/odoo/odoo/commit/a40cbf9f040338cae31eb048002e33d10ee610f0 [2]: https://github.com/odoo/odoo/commit/f983703dfa3c5102fa818523ae419a70cc4b5230
Website text animations now keep headings and paragraphs in their original layout when a selected range spans multiple text blocks. This prevents centered or structured content from shifting unexpectedly when editors apply animations in the website builder.
Original PR description
Problem: Text animation used a single span around the full selection range. When a selection crossed block elements, this placed headings and paragraphs inside a span, producing invalid HTML and changing their layout. Steps to reproduce: 1. Drag & drop a snippet (like the "Cover" block) that contains page centered text 2. Select a range of text spanning multiple block elements within the added snippet 3. Add an animation to the selected text. Solution: This PR splits the selection by block and creates one inline animation wrapper per block instead. The builder applies animation options to the resulting elements as one group, without changing the document's block structure. task-5155887
A missing view update was added so the partner autocomplete screen correctly matches a recent script change. This prevents the feature from referencing outdated interface elements and helps keep partner lookup working as expected.
Original PR description
This commit : 66889d7c42d0247d6d7b72e742c5687c65009587 changed the JS import but not the XML tag in the view. no-task
This fixes an issue where choosing an Unsplash image for records such as product images could fail during saving. The update ensures Unsplash images are properly converted and attached before the save completes, reducing errors for users editing images.
Original PR description
**Description of the issue/feature this PR addresses:** When selecting Unsplash images from a relational field (which uses `CustomMediaDialog`), the images would fail to process or link correctly to…
**Description of the issue/feature this PR addresses:** When selecting Unsplash images from a relational field (which uses `CustomMediaDialog`), the images would fail to process or link correctly to the target record. In the web editor, Unsplash image selections are handled by patching the base `MediaDialog`. When a user selects an Unsplash image, that patch intercepts the save action and uses the `unsplash` service to notify the backend. The server then fetches the external Unsplash URL and converts it into a native `ir.attachment` record before the frontend completes the save. Because `CustomMediaDialog` is a distinct component used for relational fields, it bypassed the existing `MediaDialog` patch entirely and lacked this specialized fetch-and-convert logic. This commit introduces a parallel patch specifically for `CustomMediaDialog`. It intercepts `imageSave`, routes any Unsplash records through the `unsplash` service, and replaces the raw Unsplash records with the newly generated Odoo attachments before executing the underlying save. **Steps to reproduce:** - POS > Products > Products > choose any product > click the ‘edit’ button in the image > search something, e.g. ‘burger’ > add Unsplash Access Key and Application ID when prompted > select one of the resulting Unsplash images **Current behavior before PR:** - Error when saving an unsplash image when editing product images **Desired behavior after PR is merged:** - No error when saving an unsplash image when editing product images opw-6445843 Forward-Port-Of: odoo/odoo#285954 Forward-Port-Of: odoo/odoo#283694
Point of Sale preparation tickets now use the shop's configured timezone when printing pickup or preparation times. This prevents customer receipts from showing misleading UTC times when orders are handled by automated or public system users.
Original PR description
Preparation tickets are rendered server-side for self orders. format_datetime and format_time only fall back on env.user.tz, and the render runs under whichever user triggered it: the public user for an online payment confirmed on /payment/status/poll, OdooBot for the payment cron, the self ordering default user for an OBOX print. None of them is guaranteed to have a timezone, so the ticket could be printed in UTC: an 18:15 pickup showed as 16:15 Take the timezone from res.company.tz instead. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286794 Forward-Port-Of: odoo/odoo#285370
Spreadsheet global filter labels are now easier to see. This helps users quickly identify active filters and reduces confusion when working with spreadsheets.
Original PR description
Before this commit: The global filter's pill was not visible enough for the user. Added back the "bg-primary" class that was applied in anterior versions. Task: 6535214
The accounting logo is now displayed correctly in tax return activities. This makes these activities easier to recognize and keeps the accounting experience visually consistent for users.
Original PR description
Before PR: - Accounting logo was not visible in Tax return activities. After PR: - Accounting logo is visible in Tax return activities. task-6463584 Forward-Port-Of: odoo/enterprise#130721 Forward-Port-Of: odoo/enterprise#129501
This fix prevents Point of Sale from trying to reload register data after a session has already been closed. It avoids an error that could interrupt synchronization and helps keep end-of-day register closing more reliable.
Original PR description
When the client dispatches a synchronisation right after closing the register, `_notify_synchronisation` still calls `load_data` on `current_session_id`, which is then empty. The empty session leads to an empty `pos.config`, and `product.template._load_pos_metadata` raises an IndexError while accessing `data['pos.config']['records'][0]`. Skip the loading in that case and only send the notification, as there is nothing to load without an open session. Runbot Error-[946591](https://runbot.odoo.com/odoo/error/946591) Task-[6522054](https://www.odoo.com/odoo/project/1737/tasks/6522054)
The messaging menu now presents empty tab content with better spacing and more balanced text, making it easier to read. It also clears the search field when users switch tabs, avoiding confusing filtered results from a previous tab.
Original PR description
See details in each commit. Summary: - less bloated in "channels" empty tab, with more spacing - more balanced text of all empty tabs - clear search term on tab change <img width="727" height="1142" alt="Screenshot 2026-09-09 at 00 30 13" src="https://github.com/user-attachments/assets/46acff39-ee92-4cf6-8504-c915dcc3db27" />
This fix prevents users from saving public holidays without the payroll information needed to calculate payslips. It avoids payroll creation failures when a holiday falls in the payslip period and keeps holiday records consistent across views.
Original PR description
**Steps to reproduce:** 1. Install Payroll and Time Off modules on v19.2. 2. Create a public holiday via the form view (Time Off -> Configuration -> Public Holidays). Do not enter a work entry type…
**Steps to reproduce:**
1. Install Payroll and Time Off modules on v19.2.
2. Create a public holiday via the form view (Time Off -> Configuration -> Public Holidays). Do not enter a work entry type and save.
3. Open Payroll and try to create a payslip for any employee in the same month as the public holiday you will face below traceback.
**Issue:**
The `work_entry_type_id` is required for payroll calculations. If it is null the `_round_days` calculation evaluates an empty recordset, producing a [ValueError](https://github.com/odoo/enterprise/blob/39095789c2b6a7e558d11f479a249871b3b800b6/hr_payroll/models/hr_payslip.py#L1021
).
While in this [PR](https://github.com/odoo/odoo/pull/254666/changes) made this field was made required in the
list view, it was missed in the form view. This allows users to save a holiday without a work entry type, crashing payslip generation later.
**Solution:**
Make the `work_entry_type_id` field required in the form view as well to prevent the creation of inconsistent public holiday records.
**Traceback:**
```.py
File "/home/odoo/src/enterprise/saas-19.2/hr_payroll/models/hr_payslip.py",
line 1021, in _round_days
day_rounded = float_round(days, precision_rounding=precision_rounding,
rounding_method=work_entry_type.round_days_type)
File "/home/odoo/src/odoo/saas-19.2/odoo/tools/float_utils.py", line 152, in
float_round
raise ValueError(msg)
ValueError: unknown rounding method: False
```
opw-6477587
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#285597
Forward-Port-Of: odoo/odoo#283762Inventory users without Accounting permissions can now view and create Indian E-Waybills without access errors. This removes a permission blocker in warehouse workflows and helps shipments proceed more smoothly.
Original PR description
Before this commit Inventory users without Accounting permissions could get an Access Error when viewing or creating an E-Waybill because they could not access the required document types. After this commit Inventory users can now view and create E-Waybills without an Access Error. task-6515093 Forward-Port-Of: odoo/odoo#287121 Forward-Port-Of: odoo/odoo#285023
This fixes an issue that could block users from changing the prefix or suffix on date-based sequences. The change prevents an error during editing so sequence configuration updates can be saved normally.
Original PR description
Currently an exception is generated when the user tries to change the value of `Prefix` or `Suffix` in sequence as the following steps - Create a sequence with `Use subsequences per date_range` and…
Currently an exception is generated when the user tries to change the value of `Prefix` or `Suffix` in sequence as the following steps - Create a sequence with `Use subsequences per date_range` and add any `From` and `To` dates - Save record > Change the value of `Prefix` or `Suffix` Error: `TypeError: %d format: a real number is required, not NewId` This issue was introduced by the recently refactored changes in commit [1], which added an onchange method for the prefix and suffix fields. When the user changes either field, the onchange is triggered and recomputes all dependent fields, including `_get_number_next_actual` on `ir.sequence.date_range`. During this computation, the record contains the `NewId` record. As a result, using `%03d` to format the record ID raises the reported error, since NewId cannot be formatted as an integer. This commit fixes the issue by defaulting `number_next_actual` to `0` when `_get_number_next_actual` is invoked with a `NewId` for the related sequence while computing the value during `onchange`. [1]: https://github.com/odoo/odoo/commit/387b2289da68454599666bf96844b22c41c5cc55 Sentry-7609468821 Forward-Port-Of: odoo/odoo#277766
The live map now shows technicians one by one as their locations are found, instead of waiting for every address lookup to finish. This reduces delays when using OpenStreetMap and helps dispatchers see field activity sooner.
Original PR description
Opening the live map took a long time whenever technicians were sharing their live location and OpenStreetMap was used to find their address, since only one address lookup can be done per second, and every technician had to be fully processed before anything was shown on the map. Technicians are now displayed on the map as soon as their address is found, one by one, instead of waiting for all of them at once, similar to the way customer pins are already handled. task-6524180 Forward-Port-Of: odoo/enterprise#130648
The Discuss app header now correctly sizes itself when a private chat shows both a short contact name and local time information. This prevents text from being cut off or overflowing, making chat headers clearer for users in different time zones.
Original PR description
Before this commit, when making a private chat conversation with someone with a short name and with different timezone, the header of the Discuss app was narrower than its text content. This happens because the computation of header size was not taking into account the subtitle part, which this commit fixes. Before / After <img width="172" height="60" alt="Screenshot 2026-09-07 at 21 47 21" src="https://github.com/user-attachments/assets/2644d712-4a50-4e0e-bd08-538ecc366eb9" /> <img width="189" height="62" alt="Screenshot 2026-09-07 at 21 47 07" src="https://github.com/user-attachments/assets/f0ef502c-431b-4a12-8c9a-5407460e5690" />
The AI cleanup process now correctly finds content using older embedding models when those models are retired. This helps ensure stored AI data can be kept compatible with supported models instead of being missed by scheduled maintenance.
Original PR description
The embedding model deprecation cron starts by searching for chunks that are embedded using a model that hasn't been deprecated. However, due to an optimization in the ORM (optimize_type_selection),…
The embedding model deprecation cron starts by searching for chunks that are embedded using a model that hasn't been deprecated. However, due to an optimization in the ORM (optimize_type_selection), the search doesn't return any result. A domain that uses the 'not in' operator is converted by the optimization to use the 'in' operator and the values are replaced by the difference between the available selection values (self._selection) and the values in the domain. So, given that the selection values of the embedding_model field are the non deprecated embedding models and the search domain of the cron is ['embedding_model', 'not in', non deprecated embedding models] , the final domain will be ['embedding_model', 'in', non deprecated models list - non deprecated models list] = ['embedding_model', 'in', []] which will retrieve nothing from the DB because all records have an embedding_model. The main issue is that the optimization assumes that the available selection values are static. However, an old embedding model can be deprecated and a new one added which makes the optimization fail. So, the selection values are changed to be computed dynamically which will be skipped by the optimization. Forward-Port-Of: odoo/enterprise#128130
Nilvera refund documents in Turkey are now recognized as refunds even when they arrive with positive amounts. When possible, the refund is also linked to the original invoice, improving accounting accuracy and traceability.
Original PR description
# Description of the issue/feature this PR addresses: Nilvera can send refund documents as Invoice with refund-specific InvoiceTypeCode values. # Current behavior before PR: The default UBL import logic only treats an Invoice as a refund when its amount is negative. As a result, Nilvera refund documents sent as Invoice with positive amounts are imported as invoices. Also, imported refunds are not linked to their original invoice. # Desired behavior after PR is merged: Nilvera refund documents using refund-specific InvoiceTypeCode values are imported as refunds. When a unique match is found, the imported refund is linked to its original invoice through reversed_entry_id. task-id-5948275 I confirm I have signed the CLA and read the PR guidelines at [www.odoo.com/submit-pr](http://www.odoo.com/submit-pr) Forward-Port-Of: odoo/odoo#286964 Forward-Port-Of: odoo/odoo#259672
This fix changes how mail update tracking data is packaged so it stays compact even when older database activity remains open for a long time. It helps prevent memory errors and improves reliability without changing what users see or do.
Original PR description
The store version snapshot encoded in progress transactions (xip) as a bitmap spanning the whole [xmin, xmax) range, so its size grows with how far apart those bounds are rather than with how many transactions are actually in progress. A single long-lived transaction can push that range into the hundreds of thousands, leading to memory errors, most of it being zeroes. Sending it as a list of strings is much smaller (95-98% smaller tested on odoo). 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#287191
SEPA direct debit XML files now include a special scheme name field only for Nordea countries where it is required. This prevents Italian banks from rejecting payment files that previously contained an unexpected extra field.
Original PR description
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause:…
### Issue: An unexpected `<SchmeNm><Cd>CUST</Cd></SchmeNm>` node was added inside `<InitgPty><Id><OrgId><Othr>` for all countries Some Italian banks reject SDD files containing this node ### Cause: https://github.com/odoo/enterprise/commit/3c3c64b511d07fc1ba33c30363972f5b0f7283d6 added `<SchmeNm><Cd>CUST</Cd></SchmeNm>` unconditionally for all countries The original fix was intended for Nordea (Sweden) only, which requires this node explicitly The assumption that other countries would accept it was incorrect ### Steps to reproduce: - Install `account_sepa_direct_debit` and `l10n_it` - Switch to the IT company - In Settings, set SEPA Direct Debit Creditor Identifier to `BE30ZZZ300D000000042` - Create and confirm a Payment (Method: SEPA Direct Debit, any customer and amount) - Create and validate a Batch Payment with that payment - Open the generated PAIN008 XML Before the fix, `<SchmeNm><Cd>CUST</Cd></SchmeNm>` is present opw-6530996 Forward-Port-Of: odoo/enterprise#130304
The GST token refresh process no longer overwrites the stored token with an empty or unrelated response value. This helps prevent avoidable GST reporting authentication issues while keeping the existing token valid for longer as intended.
Original PR description
Previously, `_cron_refresh_gst_token` updated the value of `l10n_in_gstr_gst_token` when refreshing the GST token using `response.get('txn')`.
However, the response received during a token refresh is: `{'status_cd': '1', 'status_desc': 'If previous Auth Token is found'}`
The GST token itself remains unchanged during a refresh; only its validity is extended. Therefore, writing `l10n_in_gstr_gst_token` with `response.get('txn')` is unnecessary and incorrect.
This commit removes that write operation.
Forward-Port-Of: odoo/enterprise#130726
Forward-Port-Of: odoo/enterprise#130313French invoices now show the “VAT due on debits” wording only when it is relevant for service taxes with a non-zero amount. This prevents misleading or unnecessary wording on export and international invoices with 0% VAT, improving invoice accuracy for French accounting compliance.
Original PR description
**Purpose** Follow-up to fix two issues reported in #277109 regarding the "TVA exigible d'après les débits" mention on French invoices. **Fixes Applied** 1. **Tax Scope Mismatch:** Changed `t.tax_scope == 'consu'` to `t.tax_scope == 'service'`. To trigger the exigibility mention on a service product, the user will configure a proper "service" scoped tax, not a goods tax. 2. **International/Export Invoices:** Added a check for `amount != 0`. Previously, the mention would print on international export invoices if the applied 0% tax had exigibility set to `on_invoice`. This hides the redundant mention for 0% exports. Forward-Port-Of: odoo/odoo#277468
Portal users can now update their preferred electronic invoicing format even when they have added a company name to their address. This prevents the field from appearing empty later and helps ensure invoice delivery settings remain accurate.
Original PR description
Steps: - Install accounting app. - Login with portal user and set `Company name` on `my/address`. - Try to edit `Electronic Format` field on my details. Issue: - `Electronic Format` field stays empty. Cause: - Since [PR](https://github.com/odoo/odoo/pull/211043) when user set `Company name` on the portal it'll create parent company and since `Electronic Format` is computed from `commercial_partner_id`, so when I update `Electronic format` field on `my/address` it'll set that value on `invoice_edi_format_store` on current address and now when I re-open `my/address` it'll compute `invoice_edi_format` from `commercial_partner_id`'s `invoice_edi_format_store` which is 'none' and it'll set `invoice_edi_format` to False and there is no way portal user can update that company's record Fix: - Update inverse of `Electronic Format` field to properly store invoice_edi_format_store value on commercial partner. Forward-Port-Of: odoo/odoo#286599 Forward-Port-Of: odoo/odoo#277527
This update removes an unnecessary warning that appeared when generating manufacturing accounting reports with demo data. It keeps the report behavior unchanged while making automated checks cleaner and reducing noise for maintainers.
Original PR description
Runbot was showing warnings when running the test_reports test with the mrp_account and project_timesheet_forecast modules installed with demo data.
```
Unknown directives or unused attributes: {'data-oe-demo'} from <t t-out="', '.join(docs.account_id.mapped('name'))" data-oe-demo="Acme Corp."/>
```
**Root cause:**
Since data-oe-demo is an html attribute usage of it within `<t>` tag raises a warning after this [commit](
https://github.com/odoo/odoo/commit/ae4824640665fc639e03a13c341f18e73060349e) in saas-19.1.
**Solution:**
Usage of span tag instead of <t> tag ensures the same behaviour without the warning.
[runbot-939604](https://runbot.odoo.com/odoo/error/939604)
Forward-Port-Of: odoo/odoo#285666This fixes an internal test issue where a shell-based test could hang when a database environment setting was present. It helps keep Odoo's automated test suite reliable and reduces delays for developers validating changes.
Original PR description
TestCommand.test_shell spawns a subprocess running `odoo-bin shell` with stdin/stdout piped through a pty. When PGDATABASE is set in the environment, that subprocess inherits it and resolves the same db_name as the parent test process, then calls Registry(dbname) to open a shell console against it. Steps to reproduce: - export PGDATABASE=db_name - ./odoo-bin -i test_core --test-tags .test_shell Forward-Port-Of: odoo/odoo#287137
Reconciliation now creates the needed exchange difference entry when matching foreign-currency journal items on accounts that allow reconciliation. This prevents leftover balances in company currency and keeps accounting records properly balanced while preserving existing behavior for non-reconcilable accounts.
Original PR description
Steps to reproduce: 1. Create two misc entries with the same foreign currency amount but different company currency amounts, on an account with "Allow Reconciliation" enabled (one debit, one credit). 2. Go to Journal Items, select both lines and click Reconcile. Issue: No exchange difference entry is generated, so the residual amount in company currency is left unbalanced. Fix: Only skip the exchange difference when the account is not reconcilable, which keeps the deferral behaviour untouched while restoring the exchange difference entry in the standard case. Causing PR: https://github.com/odoo/enterprise/pull/108362 task-6535655 Forward-Port-Of: odoo/enterprise#130541
The Hong Kong payroll payment report now handles employees who do not have an identification or passport number recorded. This prevents the report from failing and allows payroll teams to generate payment reports reliably even when optional ID details are missing.
Original PR description
When both identification_id and passport_id are empty (False), re.sub() receives a bool and raises: TypeError: expected string or bytes-like object, got 'bool'. Fall back to an empty string and normalize the passport fallback the same way as the HKID. Task-6536846
This change removes obsolete internal code across several business applications and tightens development checks around method overrides. It should make future maintenance safer without changing day-to-day user workflows.
Original PR description
https://github.com/odoo/odoo/pull/287134
This update simplifies how AI and VoIP components react to internal data changes. It supports cleaner, more consistent code with no expected impact on day-to-day user workflows.
Original PR description
Enterprise counterpart of "[REF] mail, *: drop the onUpdate option for onChange", which explains the why and the shape. https://github.com/odoo/odoo/pull/287153
This update simplifies how Odoo's web code accesses browser features, making the codebase more consistent and easier to maintain. It also improves test reliability when browser storage is unavailable, with no expected change for everyday users.
Original PR description
- enterprise: https://github.com/odoo/enterprise/pull/127791 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update simplifies how several Odoo apps access browser navigation information, replacing an older internal shortcut with a clearer approach. It should not change day-to-day user workflows, but it makes the codebase easier to maintain and test over time.
Original PR description
- community: https://github.com/odoo/odoo/pull/282230 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update modernizes internal Web Studio components to align with the latest interface framework standards. It helps keep Studio reliable and easier to maintain, with no expected change to everyday user workflows.
Original PR description
See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The website editor's row-building component was updated to use the newer supported framework behavior, reducing future maintenance risk. A related automated test was added to help ensure the collapse animation continues to work as expected.
Original PR description
Replaced `useLayoutEffect` with native OWL3 `useEffect` because `useLayoutEffect` is deprecated in OWL3. When commenting out the useLayoutEffect there was no error, the code we refactored had NO TEST coverage (see: https://runbot.odoo.com/runbot/batch/2596770/build/114856026) A HOOT test covering the collapse height animation was added to existing test (which I felt was better then adding new hoot tests).
The Knowledge app’s chatter integration was updated to use the newer framework lifecycle approach required by OWL3. This is an internal maintenance change that helps preserve existing access-rights behavior and reduces future upgrade risk, with no intended functional change for users.
Original PR description
Replaced `useLayoutEffect` with `onMounted`/`onPatched` because `useLayoutEffect` is deprecated in OWL3. Access rights are mail-store record fields mutated in place (not signals), so we keep the threadId reset and rights resolve in a single onMounted/onPatched pass to track them and avoid a race. When commenting out the useLayoutEffect there was no error, the code we refactored had NO TEST coverage (see: https://runbot.odoo.com/runbot/batch/2603405/build/115293984) NOTE: - I tried writing a hoot for this untested feature but the setup is too complex and not worth it.
This update keeps WhatsApp conversation controls working correctly by replacing an outdated internal mechanism with the current framework approach. Users should see no change in day-to-day behavior, while blocked and revived WhatsApp conversation states remain properly handled.
Original PR description
Replaced `useLayoutEffect` with native OWL3 `useEffect` because `useLayoutEffect` is deprecated in OWL3. The useLayoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - @whatsapp/composer_patch/Composer is disabled for blocked whatsapp conversations - @whatsapp/composer_patch/Disabled composer should be enabled after message from whatsapp user - @whatsapp/composer_patch/'Revive WhatsApp Conversation' button is hidden for active or blocked whatsapp channels see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2748318/build/124302613
Customer address forms in the portal have been redesigned and now adapt better to each country's address rules, including when postal codes are required or hidden. The portal address functionality has also been consolidated to simplify maintenance and improve consistency across localizations.
Original PR description
This commit improve portal address layout and refactor address logic: - Improve countrty's form view to make title bigger. - Make zip_required (boolean) field a selection field zip_applicability with not_applicable, optional and required values and update countries data, now in portal page zip will only be visible if country does not have zip not_applcable. - Merge `portal_address_extended` module in portal module to make it easier to maintain by making `portal` module dependent on `base_address_extended`. - Improve portal address layout and adapt localisation. - Also updated base_address_extended dependency to make it independent of contacts app and move `Cities` menu in contacts app and make it dependent on `base_address_extended`. task-5208254 Enterprise PR: https://github.com/odoo/enterprise/pull/112947 Upgrade PR: https://github.com/odoo/upgrade/pull/10598
This update modernizes an internal payroll screen component to stay compatible with the next version of Odoo's web framework. Existing payroll interactions, including payrun chatter controls and payslip list actions, are preserved and covered by tests.
Original PR description
Replaced `useLayoutEffect` with `onMounted` + `useBus` because `useLayoutEffect` is deprecated in OWL3. The use layoutEffect refactored in this PR had test coverage — below are some tests that failed when the effect was commented out, and are now passing: - @hr_payroll/payrun_chatter/PayRunControlPanel - chatter toggle button - @hr_payroll/payslip_list_view_filtered_payrun/Test context of PayRunCard - @hr_payroll/payslip_list_view_filtered_payrun/Test header buttons of payslip list view filtered by payrun see commented-out runbot build: https://runbot.odoo.com/runbot/batch/2748319/build/124302621
The web tour functionality has been reorganized internally so it works through the newer plugin structure while keeping existing integrations compatible. This should make future maintenance and enhancements easier without changing the day-to-day user experience.
Original PR description
Converts TourService into an owl3 Plugin (TourPlugin), keeping the legacy tour_service registration as a compatibility bridge. Extracts the tour recorder overlay/command-provider logic into their own TourRecorderPlugin and the debug-menu OnboardingItem widget. 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