Wednesday, September 16, 2026
77 changes · master
New functionality added to Odoo
Website editors can now add animated numbers that count up or down between chosen values. This helps highlight statistics, achievements, or changes more visually, with timing settings shared with appearance animations for easier setup.
Original PR description
This commit introduce a new snippet to allow users to add animated numbers (numbers that dynamically increase/decrease) on their website. By changing the start and end values, the user can have an number that increase in an animation, to emphasize an improvement or a statistic. The snippet also enable a decreasing number. Timing values (animation delay or duration) will be shared with onAppearance animations to avoid duplicating options, since in most cases the user will put the same value for both in they want to add an onAppearance animation. task-5358340
Subscription confirmations can now automatically create and manage planning shifts using the subscription dates, allocated hours, and recurring plan. When a subscription changes or ends, future shifts and recurrence settings are updated so planning stays aligned with active customer commitments.
Original PR description
- Configure shifts generated on subscription confirmation with the subscription's dates, allocated hours, and recurring plan. - Update shifts when a subscription is closed, ended, or cancelled by removing future shifts and disabling recurrence accordingly. - Update the recurrence of the shifts when the recurring plan of the subscription is updated. - Tasks are no longer recurring tasks by default when they are created from a subscription, as this behavior is now implemented to shifts instead. task-5265646
Helpdesk can now identify tickets that are similar to the one being handled, using AI-powered comparison of ticket content. This helps agents find related past issues faster, reduce duplicate work, and provide more consistent responses.
Original PR description
This commit introduce a new ticket similarity search feature which make use of embedding vectors to find similar `helpdesk.ticket` records. To do so, a new `ai.embedding.mixin` abstract class was introduced. This model contains a set of methods/fields that would be needed by any model needing the embedding capabilities. Implementation details: - Addition of a new `ai.embedding.mixin` model which contains the following method definitions: a cron job to periodically compute the embeddings of the implementing record, a method which retrieves a list of similar record ids, and some utility functions (i.e. for custom filtering when retrieving similar records). - The `_get_similar_embeddings` method of `ai.embedding` now exposes a new param `min_similarity`. If set, the param allows to filter out records below a certain threshold. task-5170315 Upgrade PR: https://github.com/odoo/upgrade/pull/11324
Enhancements to existing features
Spanish electronic invoicing now recognizes additional identity document types such as passports, residence certificates, and other official documents. This helps businesses report customer identities more accurately across Spanish EDI systems, with automatic selection of the most reliable available ID type.
Original PR description
Following the task that introduced configurable ID types, this commit adds the missing document types required for Spain: - 03 PASAPORTE - 04 DOCUMENTO OFICIAL DE IDENTIFICACIÓN EXPEDIDO POR EL PAIS O TERRITORIO DE RESIDENCIA - 05 CERTIFICADO DE RESIDENCIA - 06 OTRO DOCUMENTO PROBATORIO Validators are intentionally omitted for now. Documentation and a warning text tooltip have been prepared to guide users. For Spanish EDI systems the 'IDType' field will now compute based on a priority hierarchy. When multiple document types are available, the system will fallback and choose the most reliable option closest to zero (higher up in the priority mapping table). task-6171794 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
Resolved issues and error corrections
Users can now open the Attachments menu even when an expense attachment belongs to a company that is not currently active. The fix prevents inaccessible expense records from being read, avoiding an access error in multi-company setups.
Original PR description
**Problem:** When any expense belonging to a given company has an attachment on it, an Access Error will occur when attempting to enter the Attachments Menu when that company is not active. **Cause:** In the `hr_expense` override of `_inaccessible_comodel_records`, all `hr.expense` records are browsed, then have their values read, even if they are not currently accessible. https://github.com/odoo/odoo/blob/f28aa8e7aa0e2c6fb97c841711800410a1da3b72/addons/hr_expense/models/ir_attachment.py#L22-L23 **Purpose:** Use `_filtered_access` to ensure that only currently accessible records are read. **Steps to Reproduce in Runbot:** 1. Add an attachment to an `hr.expense` record in the My Company (San Francisco) Company. 2. Activate a different company and disable My Company (San Francisco), then attempt to open the Attachments menu in the Settings App. opw-6517249 Forward-Port-Of: odoo/odoo#286845
Website editors can now open a preview dialog that shows how selected theme colors affect common page elements. This makes it easier to judge visual impact while editing and reduces guesswork when adjusting a site's branding.
Original PR description
Steps to reproduce: - Open the website builder. - Go to Theme > Colors. - Change theme colors. - Try to evaluate the impact on UI elements. Before this commit, it was hard to understand how theme colors affected typical components while editing. After this commit, users can open a dedicated colors preview dialog (see image), and theme CSS updates are reloaded in both the page iframe and the preview iframe. task-5960098 <img width="1550" height="925" alt="image" src="https://github.com/user-attachments/assets/f80dca4f-5223-4f9f-acaf-cb9e03541cae" />
Field service shift updates now use clearer notification categories for assignments, reassignment, unassignment, rescheduling, and status changes. This helps employees receive notifications only when they are relevant to the shift status and company settings, reducing unnecessary alerts.
Original PR description
Improve shift notification tracking by using dedicated subtypes for status changes, assignment, re-assignment, unassignment, and rescheduling. Ensure notifications are only sent when relevant based on the shift state and company configuration. task-6377602
Turkish localization now lets users apply VAT withholding more easily by choosing a fiscal position for the relevant withholding ratio. This reduces manual tax changes on invoices and supports accurate withholding calculations for related e-invoicing flows.
Original PR description
Turkish VAT withholding (tevkifat) is applied at seven ratios, from 2/10 to 10/10. Before, the seven withholding taxes were not linked to the normal 20% VAT, so there was no simple way to switch an invoice to withholding. After, seven fiscal positions are added, one per ratio, plus a Domestic one. Each links the 20% VAT to its withholding group, so choosing a position and running "Update Taxes and Accounts" swaps the tax on the invoice lines. `account.tax` also gains a helper that returns the fraction a tax withholds (9/10 gives 0.9), used by the Nilvera modules. task-6368193 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Project billing reports now use clearer, more specific categories for revenue and costs. This helps project managers distinguish services, subscriptions, materials, expenses, and purchase-order-related vendor bills more accurately when reviewing profitability.
Original PR description
The billing types of an analytic line name every revenue stream in the plural, although revenue is uncountable in English, and they lump together flows a project manager reads separately: expenses only ever appear as a cost, goods and subscriptions are both reported as "Other Revenues", and a vendor bill is reported the same way whether or not it comes from a purchase order. With this PR, the revenue types are renamed to the singular and the service ones are grouped under "Service Revenue (...)", expenses are split into a cost and a revenue type, "Other Revenues" is split into "Subscriptions", "Materials" and "Other Revenue", and vendor bills billed from a purchase order get a "Purchase Orders" type. The keys are renumbered so that grouping by billing type still lists the revenue types before the cost ones, the "Other" ones last. Task-6545004
Partner ledger reports now store opening balances at accounting lock dates instead of recalculating all historical entries each time. This should make partner ledger and related customer follow-up reports faster while still reflecting later reconciliation corrections accurately.
Original PR description
Snapshot the partner ledger's initial balance at lock dates to avoid recomputing historical move lines on every report rendering. The balance is split into an init_balance and a period_balance aggregated with a groupby, the summable part of the init_balance goes through a snapshotable subengine Reconciling a partner-less line with a line having a partner moves the amount onto it, even in a locked period, so that correction stays out of the snapshots and is recomputed live on top of them. task-6235268
Turkish e-invoices now select one withholding reason at invoice level instead of requiring many tax-specific choices on each line. This reduces long tax dropdowns, prevents invalid mixed withholding ratios from being sent, and exports the reason in the correct Nilvera category.
Original PR description
A Turkish withholding invoice must carry a GİB reason code (601-627) that says why the tax is withheld. Before, this code was stored on the tax itself. The module therefore shipped one tax for every…
A Turkish withholding invoice must carry a GİB reason code (601-627) that says why the tax is withheld. Before, this code was stored on the tax itself. The module therefore shipped one tax for every (ratio, reason) pair: 138 withholding taxes in each line's dropdown. The code was also asked per line and read from the fiscal position, which only reaches the lines after "Update Taxes and Accounts", so the form asked for a reason before the matching tax was on the invoice. After, the invoice type and the list of reasons are taken from the taxes on the lines. The reason is a single field on the invoice, limited to the codes for the ratio the lines withhold, kept while it fits and cleared when the ratio changes. A missing code can be created from the field, and an invoice mixing ratios cannot be sent. On export the reason is written under the 9015 withholding category, not the 0015 exemption one. `l10n_tr_nilvera_edispatch` changes only because its tests reuse the invoice fixture from `l10n_tr_nilvera_einvoice`, which built a wrong tax; the two reference files are regenerated. task-6368193
Users can now download a version of an in-progress signing request that includes signatures and entered information already completed by other signers. The original document remains available, while the signing page continues to show only the original, making it easier to track progress without disrupting the signing flow.
Original PR description
Downloading from a sign request in progress always returned the original template document, even when some signers had already signed it. The request now serves its working copies, which already carry the values of the completed signers as incremental updates, under a "Partially signed" section of the download menu. The original documents stay available next to it, and the signing view still offers the original only. task-6469337
Changing a worksheet on a field service shift now automatically saves the shift first. This prevents users from entering information into outdated worksheet fields and helps avoid accidental overwrites or incorrect configurations.
Original PR description
Previously, when we changed the worksheet, the worksheet fields were not being changed because it required a save to update. So there were times when a user entered some data, and it updated the previous one and completely ruined their configuration. Now, when the user changes the worksheet field, the shift is automatically saved, so the user will always get only the updated fields. Task-6559528
Planning now better supports cases where an employee asks to be replaced by allowing the replacement flow to switch to that user. Button text, confirmation messages, access rules, reporting, and tests were updated to make shift switching clearer and more reliable for staff and managers.
Original PR description
Allow the adapter to switch to the user who only wants to be replaced. Change the button wording and popups of the switching scenarios --- task-5979777
Project managers can now see revenue from subscription orders under a dedicated "Subscriptions" billing type instead of mixed into "Other Revenues". This makes recurring revenue clearer in project analytic lines and improves reporting visibility.
Original PR description
Revenue invoiced on a subscription is reported as "Other Revenues", together with every other revenue that has no type of its own, so a project manager cannot tell recurring revenue apart in the analytic lines of a project. With this PR, an analytic line invoiced on a subscription order gets its own "Subscriptions" billing type. Task-6545004
The Point of Sale snooze choices now use larger rectangular buttons instead of small radio buttons. This makes the options faster to scan and easier to tap or click, improving the day-to-day user experience for staff.
Original PR description
Replacing standard radio buttons with rectangular buttons. This makes the options quicker to scan and easier to click, enhancing the overall user experience. task-6564075
Companies can now view and manage grouped tax identifier information directly on the company record, reducing the need to track many separate fields. The setup flow is also improved for country-specific identifiers, with related localization screens updated to match the new layout.
Original PR description
*:fr,ar,au,br,ca,cl,es_edi_verifactu,in,nz,ph,sa_edi,tr_nilvera_einvoice
[IMP] account,base,l10n_fr: add the identifier list on the company
A new feature to group all TIN identifiers was added on the partner, to
avoid having a huge load of fields that are hard to track.
We now display it also on the company. This PR also adds the possibility
to force the display of some additional identifiers, for an easier setup
process. (Used here to display specific French identifiers for French
companies).
[IMP] l10n_{*}: update views after base template update
*ar,au,br,ca,cl,es_edi_verifactu,in,nz,ph,sa_edi,tr_nilvera_einvoice
The vat field in the base template has changed a bit for a
new feature, this updates the view that were xpathing to it.
task-6285604Invoice emails now include the relevant timesheet report by default while avoiding unnecessary or empty timesheet PDFs. This gives customers clearer supporting details for service invoices and prevents irrelevant attachments on invoices without timesheet-based work.
Original PR description
Before this PR --- - Invoice email templates did not attach the Timesheets report by default. - The invoice email templates contained a hardcoded portal link to view timesheets. - The Timesheets report was generated from the Send & Print wizard even for invoices without timesheet-based service lines. - The Timesheets print action generated an empty PDF when no timesheet entries were available. After this PR --- - The Timesheets report is attached by default to the standard and self-billing invoice email templates. - The hardcoded portal link is removed from the invoice email templates. - The Timesheets report is generated from the Send & Print wizard only when the invoice contains timesheet-based service lines. - The Timesheets print action displays a notification instead of generating an empty PDF when there are no timesheet entries. task - 5361456
The RPC key generation dialog is clearer and now shows a ready-to-use Python example, making it easier for users to connect external tools correctly. Users can also copy the generated key more conveniently, while the clipboard button component gains more flexible icon support across the interface.
Original PR description
This commit improves the RPC key generation dialog by refining the form layout and displaying a ready-to-use Python code snippet. The key can also be copied directly using the provided copy button. Additionally, it modifies the CopyClipboardButton widget to support custom button icons while keeping `fa-clipboard` as the default. task-6375961
Dropdown menus across several Odoo areas have been standardized and visually refined to better match the new Frost design. This gives users a more consistent and polished experience when navigating options in web, email, project, and website tools.
Original PR description
*: html_builder, mail, project, website This commit standardizes dropdowns into a consistent layout and fine-tunes them to better align with the new Frost design. task-6542810 Requires: - https://github.com/odoo/enterprise/pull/130999 | Community | Enterprise | |--------|--------| | <img width="230" height="285" alt="Screenshot 2026-09-15 at 10 56 08" src="https://github.com/user-attachments/assets/b0aa7b5f-4706-4ee9-898d-0a6fc8c70dae" /> | <img width="231" height="271" alt="Screenshot 2026-09-15 at 10 54 05" src="https://github.com/user-attachments/assets/e86deed6-1552-4b19-9531-b8684d3a9b4c" /> | --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update brings the embedded spreadsheet tool up to its latest version, improving dashboards, chart behavior, pivot table accuracy, and data analysis suggestions. Business users should see more reliable spreadsheet reporting and a more consistent dashboard appearance.
Original PR description
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/4784627a29 [REL] 19.5.0-alpha.20 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0)…
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/4784627a29 [REL] 19.5.0-alpha.20 [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/e7d6e6e095 [IMP] spreadsheet: Allow integrator to set the spreadsheet dashboard [Task: 6542221](https://www.odoo.com/odoo/2328/tasks/6542221) https://github.com/odoo/o-spreadsheet/commit/14f6529b65 [IMP] colors: update dark background color [](https://www.odoo.com/odoo/2328/tasks/) https://github.com/odoo/o-spreadsheet/commit/c0f451af1e [IMP] demo: debounce xml template build [Task: 6574005](https://www.odoo.com/odoo/2328/tasks/6574005) https://github.com/odoo/o-spreadsheet/commit/aa96e07891 [FIX] demo: fix scorecard demo definition [Task: 6573109](https://www.odoo.com/odoo/2328/tasks/6573109) https://github.com/odoo/o-spreadsheet/commit/11eac2b445 [FIX] model: evaluation plugin dispatch should trigger update [Task: 6574488](https://www.odoo.com/odoo/2328/tasks/6574488) https://github.com/odoo/o-spreadsheet/commit/dc06c6a41f [FIX] chart annotation: text input style [Task: 6533642](https://www.odoo.com/odoo/2328/tasks/6533642) https://github.com/odoo/o-spreadsheet/commit/f8d1faf29b [FIX] Charts: Bubble chart background depends on color scheme [Task: 6448882](https://www.odoo.com/odoo/2328/tasks/6448882) https://github.com/odoo/o-spreadsheet/commit/8f8951738b [FIX] Charts: fix rounded borders in full-screen [Task: 6569794](https://www.odoo.com/odoo/2328/tasks/6569794) https://github.com/odoo/o-spreadsheet/commit/1efdd6cc50 [FIX] pivot: wrong running total with collapsed/hidden dimensions [Task: 6569607](https://www.odoo.com/odoo/2328/tasks/6569607) https://github.com/odoo/o-spreadsheet/commit/a709278102 [IMP] data_analysis: detection of headers [Task: 6516198](https://www.odoo.com/odoo/2328/tasks/6516198) https://github.com/odoo/o-spreadsheet/commit/736ce42775 [FIX] gaugeCharts: fix GaugeChartBuilder typing [Task: 0](https://www.odoo.com/odoo/2328/tasks/0) https://github.com/odoo/o-spreadsheet/commit/845acc4dd7 [REF] chart_suggestion_engine_test : small rewrite [Task: 6537589](https://www.odoo.com/odoo/2328/tasks/6537589) https://github.com/odoo/o-spreadsheet/commit/5d7b912754 [IMP] chart_suggestion_engine: date column [Task: 6537589](https://www.odoo.com/odoo/2328/tasks/6537589) https://github.com/odoo/o-spreadsheet/commit/84cfa4ba58 [IMP] chart_suggestion_engine: boolean column [Task: 6537589](https://www.odoo.com/odoo/2328/tasks/6537589) https://github.com/odoo/o-spreadsheet/commit/5b7222b702 [FIX] pivot: fix scope of `pivot_html_renderer` css [Task: 6523521](https://www.odoo.com/odoo/2328/tasks/6523521) https://github.com/odoo/o-spreadsheet/commit/c411984235 [FIX] standalone viewport: use correct devicePixelRatio [Task: 6445656](https://www.odoo.com/odoo/2328/tasks/6445656) https://github.com/odoo/o-spreadsheet/commit/487d50683b [IMP] model: remove notifyUser from the model [Task: 6517821](https://www.odoo.com/odoo/2328/tasks/6517821) https://github.com/odoo/o-spreadsheet/commit/681c280799 [IMP] model: remove raiseBlockingErrorUI from model [Task: 6517821](https://www.odoo.com/odoo/2328/tasks/6517821) Co-authored-by: Florian Damhaut (flda) <flda@odoo.com> Co-authored-by: Anthony Hendrickx (anhe) <anhe@odoo.com> Co-authored-by: Alexis Lacroix (laa) <laa@odoo.com> Co-authored-by: Lucas Lefèvre (lul) <lul@odoo.com> Co-authored-by: Adrien Minne (adrm) <adrm@odoo.com> Co-authored-by: Ronak Mukeshbhai Bharadiya (rmbh) <rmbh@odoo.com> Co-authored-by: Dhrutik Patel (dhrp) <dhrp@odoo.com> Co-authored-by: Rémi Rahir (rar) <rar@odoo.com> Co-authored-by: Pierre Rousseau (pro) <pro@odoo.com> Co-authored-by: Vincent Schippefilt (vsc) <vsc@odoo.com> Co-authored-by: Marceline Thomas (matho) <matho@odoo.com>
Stock screens now use clearer wording and visually de-emphasize empty values, making key information easier to scan. Manufacturing bill of materials printouts are cleaner, with unnecessary items removed and breadcrumbs fully shown for better context when printing.
Original PR description
stock ----- The name of the `Detailed Stock`-menu needed to change and the null fields were too prominent in the line so they are now muted for clarity. mrp --- The default browser print button option showed some unnecessary objects. These have been removed to improve clarity. Also the breadcrumb is now fully expanded when using the browser print option. Task-id: 6201687
Payroll line updates are now grouped together instead of handled one by one, reducing processing overhead during large payroll runs. This can make payroll generation noticeably faster, with the reported benchmark improving a 300-payslip Belgian run from about 12 seconds to about 7 seconds.
Original PR description
This commit batches the assignment in `hr.payslip.line. _inverse_name` to reduce the frequency to `write` on the field and it's calling `modified`, which is quite expensive to call. On a Belgian CP200 payrun with 300 payslips and 199 salary rules, which generates roughly 12k `hr.payslip.line`, it shaves off 4.75s of the whole creation process (from ~12s -> ~7s). Before: <img width="1917" height="296" alt="image" src="https://github.com/user-attachments/assets/45640465-09ee-43c2-861d-bf01eac35505" /> After: <img width="1917" height="346" alt="image" src="https://github.com/user-attachments/assets/30412ed4-ca68-4214-9e37-7ddeaf62427a" />
The appointment module interface has been updated to better align with the newer Frost design style. This should make scheduling pages feel more polished and consistent, improving the experience for users booking or managing appointments.
Original PR description
This PR adds some improvements to the appointment module UI Task-6533622
VoIP users can now access the queues menu while they are already on a call. This lets them join or leave call queues before their current call ends, helping control whether they receive another queued call immediately afterward.
Original PR description
Follow-up of [1], we now show the queues menu while in a call (softphone top-left dropdown menu). This allows to join/leave a queue during a call allowing/preventing a queue call to be made as soon as you hang up your current call. In any case, while in a call, you are marked as being busy from the queue point of view of course. [1]: https://github.com/odoo/enterprise/commit/7250e8dda350019f739b91fa6cc7533395ec45da task-6575682
Users can now archive, unarchive, or delete AI agents directly from agent menus. When an agent is deleted, empty chats are removed while chats with prior messages remain available as read-only history, preserving important context without allowing unavailable agent actions.
Original PR description
Adds 'Archive', 'Unarchive', and 'Delete' actions to the AI agent kanban card menu and panel menu. On agent deletion, its empty chats are deleted. Chats with existing messages are kept but become read-only where the composer and any agent-dependent actions are hidden. task-id-6570223
Belgian payroll tax reports now use configurable mappings instead of fixed salary rule codes, making it easier to adapt report boxes without developer changes. The update also separates sickness and work accident replacement revenue reporting and corrects withholding tax calculation for hourly-paid employees.
Original PR description
The reports listed salary rule codes in the code, so no rule could be added to a box without a developer. - each box now has its own category - the reports add up the payslip lines of the rules in those categories - reported amounts unchanged Task 6413398
Peppol-related errors are now shown as separate, easier-to-read items with plain-language explanations where possible. This helps users understand what went wrong with electronic invoicing and what action may be needed, instead of seeing one long technical message.
Original PR description
Before this commit, Peppol error messages (e.g. Schematron errors) were logged in the chatter as a single unformatted line and without any humanization. The errors were too technical and the user could not easily know what action to take. This PR splits the raw error payload into individual entries, maps known error codes to human-readable explanations, and renders them as an HTML list in the chatter. task-6144909 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283311 Forward-Port-Of: odoo/odoo#265253
The point of sale now remembers whether the cashier last used a percentage or fixed global discount and uses that choice as the default on the next order. This reduces repeated setup for businesses that commonly use fixed discounts, and the related label is clearer by referring to a discount value instead of only a percentage.
Original PR description
The default global discount type was always `percent`, ignoring the type the cashier last picked. Some clients prefer `fixed` and had to reselect it on every order. Save the last global discount type used in local storage and use it as the default type for the next global discount. Since the discount value is no longer necessarily a percentage, rename the "Discount Percentage" field and its label to "Discount Value". --- Task: https://www.odoo.com/odoo/project/1737/tasks/6507075 Forward-Port-Of: odoo/odoo#285353
ESG metric and action lists now open records more clearly, reducing accidental inline edits and making navigation easier. The metric form and ESG report templates were reorganized so users can find assessment details, company information, and action summaries more quickly.
Original PR description
Lists now only let you edit a record's fields once it's selected, otherwise clicking opens the form view directly. Reorganized the metric form (moved tags, grouped type/status under a new "Impact, Risk, Opportunity Assessment" section, moved company under a new "Other Info" tab). Moved the Actions appendix article to the top of the CSRD report and added a short note about what it shows, plus a few wording tweaks in the VSME report template. no-task
The Knowledge app interface has been refreshed to align with Odoo's new Frost design language. This improves visual consistency across comments, side panels, navigation, permissions, and article views, giving users a more modern and coherent experience.
Original PR description
This commit adapts Knowledge to match the new Frost design. task-6512406
AI-powered searches now return references to files instead of loading every file's content automatically. This keeps the AI context focused and allows file contents to be read only when needed, improving efficiency for searches involving attachments or binary fields.
Original PR description
Searching records sent the content of every binary field returned, filling the context with files rarely needed. The search tool now returns a reference for each of them, and a new tool reads the content of an attachment or a binary field for the records that need it. task-id-6562658
Accounting dashboards can now fully hide KPI indicators using a central system setting, extending the existing option to disable dashboard graphs per journal. For very large databases, this setting will be enabled by default to help reduce dashboard load and improve usability.
Original PR description
Currently, we give the option to disable dashboard graphs per journal via `disable_dashboard_graph`. This commit enhances this even more by adding a system parameter to hide the KPIs completely. An upgrade script will set it to True by default for any DB with over a 100k `account.move` records. task-6518856
Spreadsheet dashboards now use a background color aligned with the surrounding action view, creating a more consistent visual experience. The update also brings spreadsheet component refreshes and several quality fixes that improve printing, charts, exports, and interface behavior.
Original PR description
Task-6542221 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Self-order and kiosk orders now show a clearer reference using the customer or partner name together with the selected preset name. Each self-order configuration also gets its own unique tracking number, making it easier for staff and customers to identify and follow the right order.
Original PR description
After this commit: = - The floating order name for Self Order/Kiosk will be formatted as: `partner_name - preset_name` - Each self-order config have a unique tracking number. task-5470833 related pr: https://github.com/odoo/enterprise/pull/104163
The order status display now shows the floating order name instead of the tracking number when that name is available. Long order names are shortened on screen, making orders easier for customers and staff to recognize without disrupting the display layout.
Original PR description
After this commit: == - Floating order name will be displayed on the order status display instead of order tracking number if available - If floating order name is longer it will be truncated. task-5470833 related pr: https://github.com/odoo/odoo/pull/250288
The mail system now skips empty alias names when checking email routing. This avoids unnecessarily loading very large numbers of unnamed aliases, improving performance and reducing load for large databases.
Original PR description
`email_localparts_tocheck` might contains the empty string. It can end up fetching tons of aliases without name (2M+ in odooo.com) task-6570805 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288230
Manufacturing and barcode users now have clearer label printing choices for product and lot/serial number labels. The update adds more label formats and keeps printing available from Shop Floor and Barcode workflows, making label handling more flexible and easier to understand.
Original PR description
Split label printing into explicit product and lot/SN quality-check types. Reuse the shared Community label wizards and reports while preserving Shop Floor and Barcode application printing. This commit's changes: - Add separate Print Product Label and Print Lot/SN Label check types. - Expose the manufacturing product-label formats on quality points. - Add 4x12 and ZPL lot/SN formats with per-lot and per-unit quantities. - Route quality-check printing through the product and lot label wizards. - Adapt Shop Floor buttons and commands to the new MRP label actions. - Render location and operation-type sheets through the shared PDF report while preserving server-side PDF merging. - Update quality domains, views, tests, and client behavior for both check types. - Rename the Barcode application action from Print Barcodes to Print Labels. task-6127471
This update aligns HR, payroll, planning, appointments, attendance, leave, and timesheet features with the new rule that every employee version must have a working schedule. It also changes how flexible employees are identified, using a flexible schedule type rather than the absence of a schedule, which improves consistency in payroll and workforce planning.
Original PR description
adapting after making hr.version.resource_calendar_id required and redefining a "flexible" employee as one assigned a flexible-type calendar instead of having no calendar at all. l10n_be_hr_payroll: move l10n_be_part_time_status from the employee/contract to the Working Schedule (resource.calendar), as part-time status is now a property of the schedule. Related: https://github.com/odoo/odoo/pull/275244 Task-6296065
The Point of Sale customer list now loads more smoothly when there are many customers. Menu controls for each customer are only prepared when needed, reducing freezes on slower devices without changing the user experience.
Original PR description
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine`…
Opening the customer list with a few hundred partners freezes the UI for several seconds on a slow device (~300ms on a desktop, 5.6s with a 6x CPU throttle in the Chrome profiler). Each `PartnerLine` instantiates a full `Dropdown` for its "≡" menu. Setting up a `Dropdown` registers about ten lifecycle hooks (`useDropdownNesting`, `useNavigation`, `useDropdownGroup`, `usePopover`, `useEffect`, ...), and each hook registration eagerly allocates two `OwlError` objects to keep a stack trace. Multiplied by hundreds of rows, this dominates the render: ~60% of the click task is spent constructing errors for menus that will never be opened. Render a plain button per row instead and only mount the `Dropdown`, driven by a `useDropdownState`, once that button is clicked. The `Dropdown` opens its popover on mount when its state is already open and is unmounted again when it closes. The placeholder button keeps the classes the `Dropdown` would add to its toggler so the DOM, the styling and the tour selectors (`button.dropdown`) are unchanged. opw-6453848 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#287564 Forward-Port-Of: odoo/odoo#285974
The customer list in POS due settlement now avoids repeated due amount calculations for each row and uses the correct linked commercial partner to find balances. This makes opening large customer lists faster and reduces the risk of showing dues for the wrong customer with a similar name.
Original PR description
Opening the customer list with a few hundred partners is slow; part of the time is spent in `getPartnerCredit`. The `PartnerLine` template reads `this.partnerInfos` eight times per row, and each call runs `getPartnerCredit` again. For a contact, that method resolves the partner carrying the due by scanning every loaded partner for one named like `parent_name`, so the cost grows with the square of the number of partners. Cache the getter in a template variable so it is evaluated once per row, and resolve the due partner through the loaded `commercial_partner_id` instead of the name scan. This is also what the server sums the dues by, and it no longer picks a wrong homonym. `refreshTotalDueOfPartner` used the same lookup and now shares it. opw-6453848 Forward-Port-Of: odoo/enterprise#131079 Forward-Port-Of: odoo/enterprise#130015
This fix lets local electronic invoicing rules require a description field when needed. It helps prevent validation errors when generating or submitting electronic documents in countries or formats where that field is mandatory.
Original PR description
In a recent commit, odoo/odoo@c5037bb, we removed the product name from the description field, making the Description node optional for all localisations. This can lead to validation errors when generating or submitting electronic documents. Since individual localisations may enforce their own EDI requirements, this commit adds support for making the Description node mandatory in EDI overrides. See Also: - https://github.com/odoo/enterprise/pull/131081 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an error that occurred when users opened sale or purchase receipts from Invoice Analysis. Businesses using receipts can now review related records from reports without interruption.
Original PR description
When enabling Sale/Purchase Receipts and trying to open the form view from Invoice Analysis, an error occurs. The issue is caused by the `move_type` used in `_where()`, which includes a type that is not defined in the `move_type` field selection. Steps to reproduce: - Enable Sale/Purchase Receipts. - Create a Sale/Purchase Receipt for partner A and confirm it - Go to Invoice Analysis and open the Pivot view - Click on a cell to open partner A's receipt, then try to open the form view - Error Ticket [link](https://www.odoo.com/odoo/project.task/6462153) opw-6462153 Forward-Port-Of: odoo/odoo#288425 Forward-Port-Of: odoo/odoo#282922
Fixed an issue that stopped the Timesheet Assistant from creating a summary when users grouped more than two AI suggestions. The assistant now uses the correct lookup method, so grouped suggestions can be summarized as expected.
Original PR description
Grouping more than two Timesheet Assistant suggestions called `/ai/get_direct_response` with agent_id. That route no longer accepts an agent id: it resolves a composer from interface_key and raises 404 when none is found, so the summary never ran. Register a timesheet_assistant_ai composer and pass that key from the client. task-6570754
This fixes electronic document generation for Colombian and Peruvian localizations by ensuring required description fields are included where local rules demand them. It helps prevent validation or submission errors after a recent change made descriptions optional more broadly.
Original PR description
In a recent commit, https://github.com/odoo/odoo/commit/c5037bb, we removed the product name from the description field, making the Description node optional for all localisations. This can lead to validation errors when generating or submitting electronic documents. Since individual localisations may enforce their own EDI requirements, this commit adds support for making the Description node mandatory in specific EDI overrides. See Also: - https://github.com/odoo/odoo/pull/287566
External attendees who cannot access an unpublished appointment type will now see a warning asking them to contact the organizer instead of hitting an error page when trying to reschedule. Cancellation remains available and now takes attendees to the cancelled event page, while backend-created appointments handle reschedule and cancel actions correctly.
Original PR description
**Purpose:** To reschedule, the attendee is sent to the appointment type page to pick a new slot. That page requires read access on the appointment type, which an external attendee does not have on an unpublished appointment and they get a 403, or a 404 with website_appointment installed. **Specifications:** - An attendee with no access to the appointment type should not be allowed to select slots, so the reschedule button now returns a warning message asking to contact the organizer. - Cancelling is still allowed as it does not need that page, and the cancel button now redirects to the cancelled event page instead. Task-6570481
The Point of Sale product configurator now only shows extra-price labels when those extras will actually be charged. This prevents cashiers and customers from seeing misleading price add-ons when a fixed pricelist keeps the final product price unchanged.
Original PR description
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that…
Steps to reproduce: - Create a pricelist "TAKEAWAY" with a fixed price of 10.00 on a product whose sales price is 20.00 - Create a preset "TAKEOUT" and set its pricelist to "TAKEAWAY" - Add to that product an attribute with variant creation "Never", with a value carrying an extra price of 1.00 - In the POS, switch to the preset "TAKEOUT" and click the product Issue: The configurator advertises the attribute value with a "+ $ 1.00" badge, but that extra is charged nowhere: the title of the popup and the resulting order line both stay at the 10.00 of the pricelist. Cause: A fixed pricelist rule replaces the whole price of the product, the attribute extra prices included: _compute_price on product.pricelist.item returns fixed_price and never reaches _compute_base_price, the only place where _get_attributes_extra_price is taken into account. getPrice is a faithful port of that and overwrites `basePrice + price_extra` with rule.fixed_price. The configurator, however, rendered its badges out of value.price_extra alone, without ever asking what the pricelist of the order does with it. Fix: Only advertise an extra price when the price of the product actually reflects it, the way website_sale already does with the show_extra_price of _get_additionnal_combination_info. Asking getPrice covers more than a fixed rule: a rule based on another pricelist recurses with no extra either, and a full discount leaves nothing of it. Combo items keep their badges, since computeComboItems adds their extras on top of the combo price, like _get_combo_item_display_price does. opw-6528187 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287740 Forward-Port-Of: odoo/odoo#286475
This fixes an issue where portal users could not open chat conversations if they did not have access to the related contact record. The chat view now handles avatars in this case, restoring access to discussions from the portal.
Original PR description
Before this commit, a user was not able to access a chat if not having access to the partner. Steps to reproduce: Log in as 'Admin' and create a chat with a portal user Send a message in the same chat Log in as the portal user > My Account > Discuss go to the 'chat' tab To fix this issue, we follow a similar approach as livechat and generate the avatar in that specific case. task-6455893 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Validated time off that is shortened, such as when an employee leaves mid-leave, now keeps the employee calendar in sync instead of removing the related absence entry. This prevents payroll from incorrectly counting those time off days as worked attendance, improving accuracy for final payslips.
Original PR description
Problem ------- Fixes bug caused by PR odoo#249527. When a validated time off's dates are shortened while it stays validated (e.g. when the employee's departure date falls int he middle of the…
Problem ------- Fixes bug caused by PR odoo#249527. When a validated time off's dates are shortened while it stays validated (e.g. when the employee's departure date falls int he middle of the leave), the linked resource.calendar.leaves record was unconditionally unlinked. To reproduce: 1. Create and validate a time off request covering a whole month. 2. Register the employee's departure with a departure date in the middle of that time off. 3. Generate the employee's last payslip. The leave is correctly cut at the departure date, but since it never leaves the `validate` state, it never goes through `_validate_leave_request()` again, so its resource.calendar.leaves record is never recreated. The days that were covered by the deleted entry are no longer blocked in the employee's resource calendar, so the payslip's worked day lines (computed from resource.calendar.leaves) count them as attendance instead of time off. Cause ----- `hr.leave.write()` removed the resource.calendar.leaves record any time either the state changed away from `validate` or the leave's dates changed, regardless of whether the leave remained validated. Date-only changes on an already-validated leave never re-trigger validation, so the entry was not recreated. Solution -------- Only remove the resource.calendar.leaves record when the leave actually loses its validated state. When a validated leave's dates change but it stays validated, amend the existing resource.calendar.leaves record in place instead, falling back to creating one if none exists. Related PR: odoo#249527 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#288070 Forward-Port-Of: odoo/odoo#286465
The Spanish VAT Books report was failing to open because it referenced an outdated page element. This update aligns the report with the current interface so users can view the VAT Books report normally again.
Original PR description
The chatter icon in account_reports's line_name.xml was changed from a <button t-if="line.chatter"> to an <i t-if="this.hasChatter()">. l10n_es_reports's VatBooksLineName template still targeted the old button element, so the inherited view could no longer find its xpath target and the VAT Books report failed to render. Update the xpath expression to match the current base template structure. task-6571232
The website sitemap generation now loads only the page data it needs instead of pulling large design history fields into memory. This helps sites with many pages generate sitemaps more reliably and reduces the risk of crashes during indexing-related tasks.
Original PR description
- Before this commit: All fields of ir.ui.view were prefetched, including arch_db and arch_prev. This caused an out-of-memory issue when dealing with many pages. - After this commit: Only required fields are fetched, avoiding unnecessary memory consumption from view architecture data. opw-6470593 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284945
Website tabs using button or tab styles now correctly apply selected theme backgrounds and automatically adjust link colors for readability. This makes designed page sections more consistent with the chosen brand theme and avoids manual color fixes.
Original PR description
*: html_builder, html_editor Steps to reproduce: - Drop a tabs snippet on the website builder - Switch the style to "Buttons" or "Tabs" - Select a theme (color combination) background => It isn't applied. After this commit, the color combination is properly applied. In addition: - When a theme is selected, the links custom color is applied on inactive tabs (the active one takes the color of the theme). - When a solid or gradient background color is selected, the links custom color is applied on all links (including active), but the active button takes a default background with an opacity (white/black depending on the link's color luminance) - When selecting a background, the links color is adapted to constrast with the background. - After designing the "button" or "tabs" styles, if you go back to "underline" or "pills" styles, the colors are reset (because they cannot be adapted from those styles). task-5951656
Fixed an issue where adding a property in worksheet templates could open the setup popover in read-only mode with a broken layout. The system now checks editing permissions at the right time, so users can configure properties as expected without needing to reload the record.
Original PR description
1. Open Planning > Configuration > Worksheet Templates and open a template 2. Click "Add Property" -> the definition popover opens read-only and its layout is broken During the migration to owl3, the `useLayoutEffect` updating `canChangeDefinition` was changed to a `useEffect`. This makes it run during setup rather than after mounting, so it runs while the edit mode is still off, returns early, and never performs the check that would set `canChangeDefinition`. Due to the fact that the condition inside the `useEffect` is only present inside the `untrack`, the effect never subscribes to it, so it is only re-run when the record is reloaded and `canChangeDefinition` remains false in the meantime. With this commit, the `untrack` is dropped so that the effect subscribes to its own condition and the check runs as soon as the field becomes editable. Task-6469849
This fixes Belgian payroll leave handling so public holidays during long economic unemployment are only employer-paid within the legally allowed first 14 calendar days. It prevents incorrect payment for holidays from day 15 onward and preserves the correct final leave day in payroll calculations.
Original PR description
The employer pays a public holiday during economic unemployment only when it falls in the first 14 calendar days. The window ended one day too late, and any segment crossing it took over every remaining day. A holiday on day 15 was paid, together with the days after it, and the last day of the leave was lost. task-6566666
Sales users can once again drag and drop request for quotation files onto the Quotations list or kanban views. This fixes a failed upload message and restores the intended quick upload workflow.
Original PR description
Versions -------- - saas-19.4+ Steps ----- 1. Install Sales (with `sale_management`); 2. open Sales > Orders > Quotations; 3. drag a request for quotation file onto the list. Issue ----- The drop…
Versions -------- - saas-19.4+ Steps ----- 1. Install Sales (with `sale_management`); 2. open Sales > Orders > Quotations; 3. drag a request for quotation file onto the list. Issue ----- The drop zone appears, but dropping the file only raises a "Could not upload files" notification. Same in the kanban view. Cause ----- `UploadDropZone.onDrop` hands the dropped files to the closest input matching `.document_file_uploader.o_input_file`. Commit d1742c42 moved the RFQ upload into the cog menu with a template overriding `account.DocumentFileUploader`'s, but without forwarding `fileUploadClass` to the `FileUploader`, so that input never carried the class. This went unnoticed because `saleFileUploadListView` inherited `account.FileuploadListView.Buttons`, which renders `account.DocumentViewUploadButton` and therefore a matching (hidden) input the drop zone could fall back on. Commit 00545bdd patched `saleFileUploadListView` and `saleFileUploadKanbanView` to use the `sale_management` button templates, which inherit `web.ListView.Buttons` instead, removing that input and leaving the page with no drop target at all. Solution -------- Set `fileUploadClass` on the cog menu's `FileUploader`. The drop zone now targets the RFQ uploader itself rather than the account one, so dropped files go through `QuotationRequestUploader.getResModel` as intended. opw-testing-day-v20 Forward-Port-Of: odoo/odoo#288293
Automation rules that run when a field reaches a target value now avoid running twice during record creation. This prevents duplicate emails, activities, or other automated actions when Odoo computes a default value while creating a record.
Original PR description
An automation rule triggered when a field reaches a specific value can run its actions twice when a record is created without that field provided explicitly. For example, a rule that sends one email…
An automation rule triggered when a field reaches a specific value can run its actions twice when a record is created without that field provided explicitly. For example, a rule that sends one email and schedules two activities can send two emails and schedule four activities for one record. ### Reproduction Steps Create an automation on `crm.lead` that triggers when the stage is set to "New", with one email action and one activity action. Create an opportunity through the website contact form, which leaves the stage unset. The lead is assigned to the "New" stage, but both actions run twice. ### Cause The lead stage is computed and read during creation. That computation can trigger the automation before the creation hook processes the same record, causing both paths to run the actions. The processing code tracks records already handled during nested computations. The feedback flag used for this tracking is attached to the records, but the code checked the automation context instead. When the computation was triggered during creation, the flag was therefore missed. ### Fix Read the feedback flag from the records so nested computations update the shared tracking state. The creation hook then skips records already processed by the computation. opw-6331134 Forward-Port-Of: odoo/odoo#288222
Gantt views now correctly hide unavailable time columns even when bookings or records have no value in the grouped field. This prevents the "Undefined" row from making off-hours appear available, giving users a cleaner and more accurate schedule view.
Original PR description
Folding a column requires it to be unavailable on every row, which means ignoring the "Undefined X" one: no record stands behind it, so the server sends no unavailability for it, which reads as "available at all times" and prevents any folding. That row was spotted as the one without any record, but it gathers the records with no value on the grouped by field: a single booking with no resource in the appointment gantt was enough to bring folding back to nothing. Record-less rows are not placeholders either, as group_expand returns real ones (every resource, every employee) whose unavailabilities do count. It is now spotted through the resId its unavailabilities are read from, which is false for it whether it holds records or not.
Instagram posts now allow more time to complete when images are involved. This reduces failed posts caused by timeouts because Instagram needs to download the image from Odoo before publishing.
Original PR description
Bug === On some database on the saas, timeout issue happen for Instagram. Because Instagram downloads the image on our server, it needs more timeout than other social media. Task-6547753 Forward-Port-Of: odoo/enterprise#131632 Forward-Port-Of: odoo/enterprise#131069
Leads created from WhatsApp conversations in Discuss now automatically include the related customer contact. This prevents sales teams from receiving incomplete leads and reduces manual correction after creating CRM opportunities from WhatsApp chats.
Original PR description
### Steps to reproduce: - Install 'whatsapp', and 'crm_livechat' - Configure a WhatsApp channel and receive a message to create a conversation in Discuss - Open the WhatsApp conversation in Discuss -…
### Steps to reproduce: - Install 'whatsapp', and 'crm_livechat' - Configure a WhatsApp channel and receive a message to create a conversation in Discuss - Open the WhatsApp conversation in Discuss - Click on the 'Create Lead' smart button - Check the created lead > The Customer/Contact field is empty ### Cause of Issue: When a lead is created from a Discuss conversation, `_convert_visitor_to_lead` in `crm_livechat` attempts to set the lead's customer. It does this by checking if the channel has `livechat_customer_partner_ids`. However, in whatsapp discuss conversations, the client is saved in `whatsapp_partner_id` and `livechat_customer_partner_ids` is empty. https://github.com/odoo/odoo/blob/b8f3a5c1d2a673fd896d3b8c2968d68e9fcefe19/addons/crm_livechat/models/discuss_channel.py#L56-L58 ### Fix: Kept the fix local to `crm_livechat` and checked whether `whatsapp` is installed before reading `whatsapp_partner_id`, which would otherwise raise an `AttributeError` since `crm_livechat` does not depend on `whatsapp` and vice versa. opw-6371274 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283008
This fixes a Point of Sale issue where removing a coupon reward could prevent the customer list from opening. Staff can continue managing customers and coupon-related loyalty cards without the checkout screen crashing.
Original PR description
Steps to reproduce: - A coupon program with a coupon assigned to a customer - In the PoS, set that customer on the order - Enter the coupon code, its reward line is added - Remove the reward line -…
Steps to reproduce: - A coupon program with a coupon assigned to a customer - In the PoS, set that customer on the order - Enter the coupon code, its reward line is added - Remove the reward line - Click the customer button Issue: The customer list does not open. The PoS crashes with "TypeError: Cannot read properties of undefined (reading 'id')" raised while rendering PartnerLine. Cause: `partnerId2CouponIds` maps a partner to the ids of its `loyalty.card` records. It is filled at boot and on every `loyalty.card` create, but nothing ever removes an id from it: the models only trigger a create event. Removing the reward line of a code activated coupon deletes that card from the local models (`_setValue` in the order summary), so its id stays in the map while the record is gone. `getLoyaltyCards` pushed `models["loyalty.card"].get(id)` unconditionally, hence an `undefined` entry in the list the PartnerLine template iterates over with `t-key="_loyaltyCard.id"`. Fix: Skip the ids whose record no longer exists. The partner keeps its remaining cards, and the path where no card was deleted is unchanged. The stale id is not pruned from the map: it is reached through the reactive store proxy, and mutating it there would notify subscribers in the middle of a render. opw-6517564 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287503 Forward-Port-Of: odoo/odoo#286971
This fix ensures that when a Point of Sale session cannot be closed cleanly because its accounting entry is unbalanced, the user is shown the proper force-close wizard instead of seeing a misleading successful close. This helps prevent missing accounting entries and unposted cash differences.
Original PR description
When the closing journal entry of a session is unbalanced, `_process_session_validation` in point_of_sale rolls back the transaction and returns the "Force Close Session" wizard action, which…
When the closing journal entry of a session is unbalanced, `_process_session_validation` in point_of_sale rolls back the transaction and returns the "Force Close Session" wizard action, which `_validate_session` returns to the user so the difference can be posted on a chosen account. The pos_stock override of `_process_session_validation` calls `super()` without returning its result. The action is dropped, `_validate_session` carries on, and the session is written as `closed` while the rolled-back entry no longer exists: `move_id` is empty, the orders stay in `paid`, `cash_real_transaction` stays at 0 and the cash difference is never posted. The user sees a successful close and nothing in accounting. Steps to reproduce: - Use a stock configuration whose costs yield a rounding difference on the closing entry (e.g. AVCO products with a sale and a return whose unrounded costs round differently when split between the expense and valuation lines). - Close the session from the PoS. - The session is closed, no journal entry exists, and no wizard was shown. Return the result of `super()` so the wizard is shown as in 19.0. opw-6543863 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287618
Point of Sale cash register closing messages now correctly include cash in/out entries made by POS administrators who do not have accounting permissions. This prevents false closing differences from appearing after a register is closed, improving trust in cash control reports.
Original PR description
Steps to reproduce: - Give a user PoS Administrator rights and no Accounting rights. - As that user, open a session with cash control, sell something paid in cash and do a Cash Out. - Close the…
Steps to reproduce: - Give a user PoS Administrator rights and no Accounting rights. - As that user, open a session with cash control, sell something paid in cash and do a Cash Out. - Close the register. The closing popup shows the expected cash (opening + cash payments - cash out); enter exactly that amount, the popup shows no difference. - Open the closed session: its chatter says "Closing difference: -X", X being the cash out amount, and "Closing expected" is the amount before the cash out. Issue: The closing control data agrees with the user, but the closing message records a cash difference equal to the cash out. Cause: `_compute_cash_balance` sums `statement_line_ids` with the rights of the current user. Cash moves are `account.bank.statement.line` records, which `_inherits` `account.move`, so the account.move record rules apply to them too. For a PoS user the only such rule is `rule_invoice_pos_user` (`pos_order_ids != False`), and a cash move has no PoS order: unless the user is in `account.group_account_invoice`, their own cash moves are filtered out and `cash_register_balance_end` ignores them, while `get_closing_control_data` sums the lines in sudo. Since da8be203ec32 PoS managers can create cash moves without any accounting group, which made this visible: in 18.0 cash in/out required `account.group_account_invoice`, whose `account_move_see_all` rule makes every move readable. The values stored at closing are right by accident: `_validate_session` reads the lines in sudo just before, and the one2many cache is shared between the sudo and non-sudo environments of the same transaction. The message posted by `update_closing_control_state_session` runs in its own transaction and gets the filtered sum. Fix: Read the cash lines in sudo in `_compute_cash_balance`, as `get_closing_control_data`, `get_cash_in_out_list` and `_validate_session` already do. Users with accounting rights see all lines already, so nothing changes for them. opw-6521591 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#287741 Forward-Port-Of: odoo/odoo#286308
This fixes a Point of Sale issue where selling multiple physical gift cards with the same value could combine them into one order line, preventing staff from entering a unique code for each card. Orders with multiple gift cards should now validate and sync correctly, reducing checkout failures and duplicate-code problems.
Original PR description
Steps to reproduce: - Create a gift card program (several programs sharing the same gift card product show the same issue) - In the PoS, sell a physical gift card: click the gift card product and set…
Steps to reproduce:
- Create a gift card program (several programs sharing the same gift card product show the same issue)
- In the PoS, sell a physical gift card: click the gift card product and set a code through "Sell physical gift card?"
- Click the gift card product again to sell a second physical card of the same value
- Validate the order
Issue:
The second unit is merged into the already coded orderline (one line, qty 2, one code), so the "Sell physical gift card?" link is no longer displayed and the second code cannot be entered. Validating the order then fails with "The operation cannot be completed: A coupon/loyalty card must have a unique code." and the order stays unsynced: the qty 2 line is split into two point entries both carrying the same gift_code, so two loyalty.card records are created with the same code.
Cause:
_setupGiftCardOptions() (and setupEWalletOptions()) pass merge=false so that a gift card line is never merged, and until 17.0 add_product() honored it ("options.merge !== false"). The 18.0 store refactoring dropped it: addLineToOrder() decides merging from a local variable that is only set to false when a price_unit is given in vals, and never reads opts.merge. The option became dead code, in point_of_sale's addLineToOrder as well as for the pos_discount caller.
Fix:
Honor opts.merge === false in addLineToOrder(). Callers that do not pass the option are unaffected, so the default merging behaviour is byte-for-byte the same; only the callers explicitly forbidding a merge (gift card, ewallet and discount lines) get their pre-18.0 behaviour back.
opw-6466324
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#287486
Forward-Port-Of: odoo/odoo#286237Preparation tickets from self-order flows are now sent through the Odoo Box point-of-sale printing setup. This helps kitchen or preparation staff receive the right tickets when customers place orders themselves, reducing missed or delayed order preparation.
Original PR description
Following this commit : ==== - Preparation ticket will be printed through obox in self order task-6255005 Related PR : https://github.com/odoo/odoo/pull/269216
Customers switching from store pickup to a country-specific delivery option now see the correct delivery charge instead of it remaining free. This prevents misleading checkout totals and ensures eligible delivery methods are priced using the customer's address.
Original PR description
Steps to reproduce: - Install eCommerce and Click & Collect. - Publish Pick up in store with a warehouse whose address is in country A (e.g. United States). - Publish a country-specific delivery…
Steps to reproduce: - Install eCommerce and Click & Collect. - Publish Pick up in store with a warehouse whose address is in country A (e.g. United States). - Publish a country-specific delivery method (Fixed Price, non-zero) limited to country B (e.g. Spain). - On the shop, checkout with a delivery address in country B. - Select Pick up in store, then select the country-specific method. Issue: Selecting the country-specific method keeps Delivery at 0 (Free). The same happens with country-restricted connectors: `/shop/set_delivery_method` never applies the method, so no rate is requested for that switch. Cause: Since saas-19.3, a pickup location replaces `partner_shipping_id` with a generated pickup address. `/shop/set_delivery_method` only calls `_set_delivery_method` if the method is in `_get_delivery_methods()`, which matches on the shipping address. The pickup country makes the country-specific method look unavailable, so it is never applied. The order still has the pickup method (0 delivery), and the summary reports the selected method as Free. Match availability on the customer when shipping is a pickup address, and restore that address before rating the method that is being set. Keep the Based on Rules check so a method with no applicable price rule is not listed after pickup. opw-6493956 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#285068
This fix removes leftover component records that could be created when users manually adjust subcontracted production components. It helps prevent later inventory reservation and transfer validation errors caused by incomplete background records.
Original PR description
#### Issue When manually adding component lines in the subcontracting Record Production flow, extra stock move lines can remain in the database without a linked stock move. Those lines have no…
#### Issue When manually adding component lines in the subcontracting Record Production flow, extra stock move lines can remain in the database without a linked stock move. Those lines have no move_id, so their related state is empty. They can later be selected by stock reservation code and cause validation errors when processing the transfer. #### Steps to reproduce 1. Create a subcontracted product. 2. Confirm a subcontracting receipt/purchase flow for that product. 3. Open the subcontracting Record Production popup. 4. Remove an existing component line. 5. Add a new component line for another storable product available at the subcontractor location. 6. Save/record the production. 7. Check stock.move.line records , Inventory > History > Group By Status. An extra stock move line is left with no move_id. #### Root cause The inverse of `mrp.production.move_line_raw_ids` already collects and deletes move lines detached from existing raw moves. However, when the user adds a new component product, the inverse creates a new additional raw move. Creating that raw move can also create reserved move lines. The inverse then replaces `move.move_line_ids` with the user-entered lines, but it did not collect the newly created reserved lines before replacing them. Those reserved lines were detached from the move and left in the database as orphan stock move lines. #### Fix Apply the same cleanup logic to newly created additional raw moves: collect their auto-created move lines before replacing `move_line_ids`, then unlink those detached lines at the end of the inverse. opw-6304649 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#281864 Forward-Port-Of: odoo/odoo#276235
Voice transcription requests are now sent in a format compatible with the updated service connection. The client also reads the new response format correctly, helping prevent transcription failures for call recordings and VoIP-related workflows.
Original PR description
Ok got it. 3 separate issues. 1st When we send audio for the transcription we used to send that over http, where we could have raw bytes, now we use json rpc, so we should base64 encode it first, addressed here 2nd When iap, requests the transcription request, and pipes it to the AI provider, it tries to unpack usage from the request. Which in the case of the VTT raw response is not there. Fixed here 3rd is that when odoo-client receives the transcription it tries to unpack the results. It looks for `result` key which got updated to `text` Thought about updating it on the iap side, but I see that realtime already uses it, so maybe let's keep it similar, so just updated it here This pr fixes 1s and 3rd, 2nd fixed on the iap side here https://github.com/odoo/iap-apps/pull/1909
Corrects how fixed-rate taxes are calculated on Mexican electronic payment complements when an invoice is partially paid. This helps prevent payment CFDIs from being rejected by Mexican tax authorities or certification providers due to small tax amount mismatches.
Original PR description
When generating a payment complement, tax base and importe coming from the related invoice are prorated by the percentage actually paid, each rounded independently to the currency precision. The…
When generating a payment complement, tax base and importe coming from the related invoice are prorated by the percentage actually paid, each rounded independently to the currency precision. The post-fix step that restores the SAT invariant uses a Tasa-only formula (`base = total / (1 + rate)`), so Cuota (fixed amount per unit) taxes keep mismatched values, ending up with `ImporteDR != round(BaseDR * TasaOCuotaDR)`. This leads to CFDIs rejected by the PAC/SAT. Steps to reproduce: - Create a customer invoice with a Cuota IEPS tax (e.g. 26.2569). - Register a partial payment whose amount is not an exact divisor of the invoice total (e.g. one third). - Send the payment CFDI: the resulting Cuota TrasladoDR has an ImporteDR that does not match BaseDR * TasaOCuotaDR, leading to a rejected CFDI. This commit recomputes `importe` from the prorated `base` for Cuota taxes (bypassing the Tasa post-fix) opw-6087564 Forward-Port-Of: odoo/enterprise#131436 Forward-Port-Of: odoo/enterprise#113395
Australian payroll users can now register super payments successfully even when they open a super contribution from the Pay Runs kanban view. This prevents an incorrect pay run status from being applied to the payment process, avoiding an error and making the workflow consistent across entry points.
Original PR description
Current behavior: -- Registering a super payment from a pay run opened out of the Pay Runs kanban fails with "Wrong value for account.payment.state. The same super contribution registers without…
Current behavior: -- Registering a super payment from a pay run opened out of the Pay Runs kanban fails with "Wrong value for account.payment.state. The same super contribution registers without error when opened from Payroll > Reporting > Australia > Super Contributions. Expected behavior: -- Register Super Payment should work regardless of how the super contribution record was reached. Steps to reproduce: -- - Take an Australian pay run through to Paid - Open Payroll > Payslips > Pay Runs, kanban grouped by Status (default) - Open the pay run from the Paid column, then Super Submissions - Lock the super contribution and click Register Super Payment Cause of the issue: -- The Pay Runs kanban is grouped by state, so the web client adds default_state to the context of records opened from a column. That context follows the smart button into action_register_super_payment, where account.payment is created without an explicit state. The ORM applies default_state from the context which is a hr.payslip.run value that account.payment.state does not accept. The same leak reaches account.move through action_post, which creates the payment journal entry. Fix: -- apply with_context(clean_context(self.env.context)) to the recordset to remove the default_state key opw-6478084 Forward-Port-Of: odoo/enterprise#128724
Subscription invoices now use the earliest deferred start date across all invoice lines when setting subscription or upsell log effective dates. This prevents later invoice lines from overriding the correct start date, improving accuracy for subscription tracking and reporting.
Original PR description
When posting a subscription invoice, each invoice line overwrites the effective date of the subscription or upsell logs. The last line therefore determines the date, even when another line has an earlier deferred start. Use the earliest deferred start date on the invoice, falling back to the invoice date when no deferred start date is set. Forward-Port-Of: odoo/enterprise#131512
Portal users can now submit product reviews with attached files without hitting a misleading “Not Found” error. The fix ensures the website’s review settings are checked correctly during attachment uploads, so enabled review features work consistently.
Original PR description
A portal user cannot add an attachment when posting a review on a product page: submitting the review with a file attached fails with a generic "Not Found" error, while posting the exact same review…
A portal user cannot add an attachment when posting a review on a product page: submitting the review with a file attached fails with a generic "Not Found" error, while posting the exact same review without an attachment works fine.
Steps to reproduce:
-------------------
* Enable "Discussion and Rating" on a product page (Website > Customize)
* Log in as a portal user and open that product page
* Write a review, attach a file, then submit
> Observation:
"Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
Why the fix:
------------
`product.template._get_mail_message_access()` demotes a portal user's create access to 'write' whenever
`env['website'].is_view_active('website_sale.product_comment')` is False, since 'write' access is a deliberate way to block posting when the feature is toggled off for the website. `is_view_active` only picks the correct, website-specific view when `website_id` is present in `self.env.context`; that key is injected by the website frontend only for routes declared `website=True`.
`/mail/attachment/upload` is not `website=True` (attachments used to go through the dedicated, `website=True` `/portal/attachment/add` route, removed when portal's attachment uploader was unified with mail's), so `website_id` is missing from context on that route, `is_view_active` falls back to the generic, shipped-`active="False"` view, and always reports the feature as disabled - even when it is actually enabled for the current website. Create access is then wrongly demoted to 'write', which a portal user never has on `product.template`, so the thread lookup fails and the controller raises `NotFound()`.
Resolve the current website from the request itself (`env['website'].get_current_website()`) and inject its id into context before checking `is_view_active`, instead of relying on `website_id` already being in context. This makes the check accurate regardless of which route triggered it.
opw-6539184
Forward-Port-Of: odoo/odoo#288116
Forward-Port-Of: odoo/odoo#287345Product carousels in single-scroll mode now slide correctly on right-to-left language websites such as Arabic. This prevents empty spaces and image distortion, giving visitors a smoother browsing experience.
Original PR description
**Description of the issue/feature this PR addresses:** When a dynamic product carousel is set to single-image scrolling mode in an RTL language (e.g., Arabic), sliding between items behaves…
**Description of the issue/feature this PR addresses:**
When a dynamic product carousel is set to single-image scrolling mode in an RTL language (e.g., Arabic), sliding between items behaves inconsistently, resulting in empty spots or temporarily distorted images.
This occurs because the DOM manipulation creating the infinite scroll was coded for LTR physical movements. In LTR, the first DOM element is visually on the left. In RTL, the visual layout is mirrored, with the first DOM element visually on the right. When we then trigger a "left" slide in RTL, the LTR-based JavaScript doesn't appropriately move the last element to the first index prior to the animation, resulting in an empty gap, among other issues.
This commit resolves the issue by checking the document's text direction. By swapping the target direction ("left" or "right") in onSlideSingleScroll and onSlidSingleScroll when RTL is active, the underlying array operations now correctly align with the animation.
**Steps to reproduce:**
- Website > Edit > add Product Carousel > Customize > change Scrolling Mode to Single
- Website > Edit > Theme > Website > Language > change to Arabic
- Click the arrows in the product carousel > observe inconsistent scrolling with visual glitches
**Current behavior before PR:**
- Visual glitches when sliding carousels in single-image scrolling mode for RTL languages
**Desired behavior after PR is merged:**
- No visual glitches when sliding carousels in single-image scrolling mode for RTL languages
opw-6490277
Forward-Port-Of: odoo/odoo#286042This fix keeps existing guided tours from breaking when they contain an older extra field. It helps ensure previously exported custom and industry tours continue loading normally without requiring manual updates.
Original PR description
Tours exported between 37b35f18 and d2ee747d carry a stray `url` key. `validate()` throws on any unknown key at `registry.addValidation()` time, which aborts asset loading for those pre-existing custom tours. Add a `"*"` wildcard to the schema: unknown keys are ignored, `steps` is still validated. 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#287807 Forward-Port-Of: odoo/odoo#287617
Customer invoice numbering now ignores vendor bill numbers, preventing the two document flows from accidentally sharing the same sequence. This helps businesses keep official Dominican electronic invoice numbers accurate and avoids confusion or compliance issues caused by skipped or incorrect numbering.
Original PR description
### Issue before this commit: When users enabled the "Use Documents" option on a Purchase journal and created a vendor bill with a specific document type (e.g., type 31) and number (e.g., E3100056),…
### Issue before this commit: When users enabled the "Use Documents" option on a Purchase journal and created a vendor bill with a specific document type (e.g., type 31) and number (e.g., E3100056), creating a new customer invoice with the same document type would incorrectly continue the sequence from the vendor bill's number (e.g., E3100057). ### Steps to reproduce the issue: 1. Download Accounting and l10n_do_edi 2. Go to invoices and vendor bills and delete all of them 3. Go to Journals and tick Use Documents options for Sales and Purchases journals 4. Create a vendor bill setting the document type as for example (31) Electronic Tax Credit Invoice and the document number as for example E3100056 5. Create an invoice and set the same document type 6. See that the sequence will increase by 1 but starting from the last number setted (so it will be E3100057) when you create a new invoice ### Cause of the issue: https://github.com/odoo/enterprise/blob/d4da04a036486818c12712a200a3482a66921abf/l10n_do_edi/models/account_move.py#L346-L354 The _get_last_sequence_domain override is fetching the last sequence across the company based on the document type, but it did not filter by move_type. Consequently, it was catching vendor bill numbers (in_invoice) to compute the next sequence for customer invoices (out_invoice). ### Reason to introduce the fix: Restrict the sequence lookup to sales documents will ensures that vendor bill references do not interfere with the official sequential numbering of customer invoices. opw-6430906 Forward-Port-Of: odoo/enterprise#128178
Large blog imports now process link updates in smaller controlled batches, preventing timeouts during website content generation. This helps ensure imports complete reliably instead of stopping partway through.
Original PR description
This commit fixes an issue where huge blog requests were timing out due to large replacements for links that weren't controlled with our batch creation wrapper. This resulted in incomplete imports. The fix is to put the text replacements in the batch create wrapper which will avoid timeouts and let it continue reliably. Forward-Port-Of: odoo/enterprise#131368
Salespeople now receive the expected upsell warning when multiple timesheet entries together exceed the prepaid service threshold. This helps teams catch upsell opportunities even when customer work is logged incrementally rather than all at once.
Original PR description
Steps to reproduce: -------------------------------------------- 1. Install `sale_timesheet` module 2. Create a product with: * Type: Service * Invoicing Policy: Prepaid/Fixed Price * Create on…
Steps to reproduce:
--------------------------------------------
1. Install `sale_timesheet` module
2. Create a product with:
* Type: Service
* Invoicing Policy: Prepaid/Fixed Price
* Create on Order: Project & Task
* Upsell Threshold: Set some value (e,g. 600%)
3. Create and confirm the sale order with that product
4. Create and confirm an invoice for the sale order
5. From Recorder Hours Smart button:
* Add two timesheets for hours 3 & 4 (Combined h > Threshold Percentage/100)
Observation:
--------------------------------------------
* When adding a single 7h timesheet, an upsell warning activity is correctly created for the salesperson in the chatter.
* When adding multiple incremental timesheets whose combined duration exceeds the threshold, no upsell warning activity is created.
Issue:
--------------------------------------------
* The `_compute_field_value` method filters on `invoice_status != 'upselling'` before recomputing the new invoice status.
* After the first incremental timesheet is added, the sales order already has the upselling status from the previous computation.
* As a result, subsequent computations skip the upsell activity logic, even though `has_displayed_warning_upsell` is still `False` and no warning activity has yet been created.
Solution:
--------------------------------------------
* Removes the `so.invoice_status != 'upselling'` condition from the filter.
* The order-level `invoice_status` was never the right place to control upsell activity creation. An order can have `invoice_status == 'upselling'` for various reasons (delivered > invoiced), but that doesn't mean all lines have already triggered their upsell warnings.
opw-6117754
Forward-Port-Of: odoo/odoo#287642
Forward-Port-Of: odoo/odoo#266275This update makes marketing campaign webhooks more reliable by better validating incoming data, avoiding unintended record creation, and improving error logging. It also restores and cleans up marketing automation views, helping teams diagnose campaign activity issues more easily after recent refactoring.
Original PR description
Provide various fixes after recent marketing automation refactoring. Notably * improve defensive webhook behavior, sanitize input, improve logging; * various views fixup, notably introducing back a generic activity view for debugging; * fix various small code issues; See commits for more details. Task-6559148 Followup of Task-3866422 (PR odoo/enterprise#113376)