Wednesday, September 9, 2026
47 changes · saas-18.3
Security fixes and vulnerability patches
Neutralized database copies will no longer retain real OpenAI or Google API keys. This prevents copied databases from making AI provider calls using a customer’s credentials, reducing the risk of unintended usage or exposure.
Original PR description
Currently if you were to get a dupe of a database with credentials for either OpenAI or Google, the api keys will be present in the neutralized database. This is problematic because API calls can still go through with the client's credentials
New functionality added to Odoo
Belgian companies can now generate SAF-T reports directly in Odoo. This supports local audit and reporting requirements by making standardized tax audit files available for Belgium.
Original PR description
SAF-T reports can now be generated for Belgium. task-5129628 Forward-Port-Of: odoo/enterprise#107270
Enhancements to existing features
Digitally signed PDFs now include visible and embedded information about the database and base URL they came from. This makes it easier for recipients and businesses to verify the origin of official PDF documents.
Original PR description
Before this commit, the digitally signed PDF had no mention of the database or the base URL. This commit adds visible information and metadata to allow checking more easily the origin of the file. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Resolved issues and error corrections
Refreshing the attachment view from an expense report now keeps the view limited to the relevant expense receipt. This prevents users from unexpectedly seeing a broader list of readable attachments and keeps the workflow focused on the selected expense.
Original PR description
Scenario: - go on an expense with an attachment (or add it with "Attach Receipt") - go to View Report then in the expense list view, click on the attachment icon - you see only the expense attachment, then refresh the page Result: you see all the (readable) attachments of the database Cause: since we are giving the id of the action base.action_attachment (action used to show all Attachments), on reload we apply that action and the domain is lost. Fix: remove the id of the action so on reload we just keep the current "custom" action parameters. opw-6514407 Forward-Port-Of: odoo/odoo#286220
This change adds support for the Belgian Blackbox v2 fiscal compliance device in Odoo Point of Sale. It helps Belgian businesses using POS meet updated legal requirements while also adjusting related payment, session, and order handling to work correctly with the new integration.
Adds support for the new Belgian Blackbox v2 requirements in Odoo Point of Sale. This helps Belgian businesses using certified POS systems stay compliant with updated fiscal signing and reporting rules for sales, refunds, pre-bills, order changes, and cash movements.
Odoo can now restart its main server without interrupting most incoming requests when the new graceful reload option is enabled. This improves service availability during maintenance or updates, while also fixing small server worker handling issues that could cause errors or duplicate actions.
Original PR description
Before, the only reload option that existed was the `server_phoenix` mode that reexecuted the server upon receival of the SIGHUP signal. This came with a consequential downtime while the server was…
Before, the only reload option that existed was the `server_phoenix` mode that reexecuted the server upon receival of the SIGHUP signal. This came with a consequential downtime while the server was restarting. We add the option that allows to reload the server with no downtime, by adding the environment variable ODOO_GRACEFUL_RELOAD=1 (POSIX + Prefork mode) With this environment variable is set and a SIGHUP signal is sent to the main server, it will initiate the shutdown procedure in a separate process that will first wait until the main process has finished restarting and is ready to handle new incoming HTTP requests. The reexecuted server will reuse the same socket and notify its stopping fork with a SIGHUP signal, which will then proceed with the graceful shutdown procedure. It will not be able to reap the children processes, so it will monitor them closely in a slightly different way using psutil. The newly restarted server will reap them without consequence. Note: the gevent longpolling server is not handled gracefully. (This comes along with 2 small fixes.)
Finnish electronic invoicing now includes support for a new XML invoice format aligned with Finvoice 3.0 requirements. This helps businesses operating in Finland prepare compliant invoice files and lays the groundwork for future Finvoice EDI workflows.
Original PR description
This commit add a new invoice xml format, following Finvoice 3.0 requirements. See legal requirements in the task. task-4500798 Forward-Port-Of: odoo/enterprise#80590
Partner pricelist assignment now uses the parent partner's grade pricelist when no other pricelist can be found. This helps ensure related partners receive an appropriate pricing setup automatically, reducing manual corrections and inconsistent pricing.
Original PR description
This commits modify the pricelist assigning method so that if no other pricelist is found, the pricelist of a partner will be the pricelist found in the grade of its parent. TASK-4985900
Messaging screens now have more consistent and polished action menus across Discuss headers, sidebars, chat windows, messages, attachments, and composers. This improves usability by making common actions easier to recognize, while also refining chat bubble previews and several small visual details.
Original PR description
- improved thread actions style: discuss header, discuss sidebar, chat windows - chat bubble message preview uses bubble color of last message - minor miscellaneous tweaks
Odoo now has a cleaner way to refresh or shut down messaging data in the background, helping avoid stale information and test side effects. This prepares live chat and mail features to recover more reliably if updates are missed for an extended period.
Original PR description
This commit adds `store.destroy()` to cleanly destroy the store, including ongoing reactive observers. This is useful to make sure no side-effect store among HOOT tests This commit adds `store.reset()`, to make the store fresh as at page load. This is in preparation to make store reset in case we miss notifications for a long time. https://github.com/odoo/enterprise/pull/85615
This update improves how messaging data is cleared and rebuilt in the background, helping keep chat and AI assistant interfaces consistent after resets or page changes. It also fixes related Web Studio test coverage to ensure report editing behavior remains stable.
Original PR description
https://github.com/odoo/odoo/pull/210139
Messaging actions now have a more consistent and polished look across Discuss, chat windows, live chat, WhatsApp, AI, and Knowledge areas. This makes thread controls easier to recognize and improves message preview consistency, creating a cleaner communication experience for users.
Original PR description
- improved thread actions style: discuss header, discuss sidebar, chat windows - chat bubble message preview uses bubble color of last message - minor miscellaneous tweaks
Updates the Dominican Republic accounting localization to apply the ISR withholding rates required by Law 30-26 from July 2026. This helps companies calculate and report the correct withholding amounts for services, rentals, foreign payments, transfers, and other income categories.
Original PR description
## Description Law no. 30-26 of June 18, 2026 updates Dominican ISR withholdings effective **July 1, 2026**: - **Professional services, fees, commissions, and rentals paid to individuals:** 10% to…
## Description Law no. 30-26 of June 18, 2026 updates Dominican ISR withholdings effective **July 1, 2026**: - **Professional services, fees, commissions, and rentals paid to individuals:** 10% to 15%. - **Specific foreign-payment categories:** 15% for royalties or rights, software licenses, online advertising, and the use or storage of data. - **General remittances abroad:** remain at 27% when they are outside those specific categories. The DGII's current **IR-17-2026 (July 2026 onward)** also confirms that the concepts discussed in review are three distinct reporting rows: - **Row 4 — Transfers of titles and properties:** 2%. - **Row 17 — Other income under Decree 139-98, Article 70(a)/(b):** 3%. - **Row 18 — Other withholdings under General Rule 07-2007, as amended by Law 30-26:** 3%. The two 3% rows must not be conflated with each other or with the separate 2% transfer withholding. ## Implementation The changed-rate template entries use new, rate-explicit XML IDs, as recommended in review: - `ret_15_income_person`: new -15% fee withholding, replacing `ret_10_income_person` in the template; posts to `21030301`. - `ret_15_income_rent`: new -15% rental withholding, replacing `ret_10_income_rent` in the template; posts to `21030302`. - `ret_3_income_person`: new -3% General Rule 07-2007 withholding, replacing `ret_2_income_person` in the template; posts to `21030308`. - `tax_group_person_services_15`: new grouped tax using `ret_15_income_person`. - `tax_group_person_construction_3`: new grouped tax using `ret_3_income_person`. - `position_person_services_15`: new physical-services fiscal position mapped only to the current 15% grouped tax. The remaining legal concepts stay separate: - `ret_3_income_article_70`: new -3% tax for Decree 139-98, Article 70(a)/(b), posted to `21030309`. - `ret_2_income_transfer`: remains at -2% on `21030306`; its misleading “Materials” source metadata is corrected to transfers of titles and properties. - `ret_27_income_remittance`: remains active at -27% on `21030307`, with the general foreign-services fiscal position unchanged. - `ret_15_income_foreign_royalties_technology`: new -15% tax only for the foreign categories covered by Law 30-26. It posts to the new `21030310` Law 30-26 payable account rather than the L253-12 remittance account. - `position_exterior_royalties_technology`: new fiscal position mapping purchases only to that specific 15% tax. The specific foreign tax keeps the short invoice label `-15% ISR (L30-26)` to avoid wrapping in vendor-bill PDFs. The original manifest author entry is unchanged, as requested. The Git history and corporate CLA record this contribution by Grupo de Consultoria Henca. ### Existing-company reload behavior The superseded 10%/2% tax, grouped-tax, and physical-services fiscal-position rows are removed from the template rather than shipped as obsolete entries to new companies. On an existing company, Odoo's chart reload keeps those historical records and generated XML IDs unchanged, then creates the new current-rate records under the new XML IDs. On a newly loaded chart, only the current template entries are created. The physical-services fiscal position also has a new XML ID intentionally. Reload preserves existing fiscal-position mappings as user-configurable data and only appends mappings involving new taxes; reusing `position_person` could therefore leave both the historical and current destinations on one position. `position_person_services_15` keeps the current mapping isolated while the old position remains available for historical operations. `ret_2_income_transfer` keeps its existing XML ID because its legal rate, concept, and account remain 2% / transfers / `21030306`. The corrected label is present for new charts; backfilling label-only metadata on already-loaded charts would require an explicit upgrade migration because standard chart reload does not rewrite that user-visible metadata. ## Official references - DGII, current IR-17-2026 download page (July 2026 onward): https://dgii.gov.do/herramientas/formularios/formularioDeclaraciones/Paginas/impuestosRetencionesyRetribuciones.aspx - Law 30-26: https://www.consultoria.gov.do/Consulta/Home/FileManagement?documentId=3405887&managementType=1 - DGII implementation calendar, notice 10-26: https://dgii.gov.do/publicacionesOficiales/avisosInformativos/Documents/2026/10-26.pdf - DGII CA59, calculation for professional and technical services: https://ayuda.dgii.gov.do/conversations/retenciones-y-retribuciones-complementarias/ca59-qu-porcentaje-del-isr-deben-retener-las-personas-jurdicas-a-las-personas-fsicas-en-la-prestacin-de-servicios/5f3c175f8cd858ce879a130f - DGII clarification for General Rule 07-2007 and the construction sector: https://ayuda.dgii.gov.do/conversations/discusiones/aplicacin-de-la-ley-nm-3026-respecto-a-la-retencin-prevista-en-el-artculo-3-de-la-norma-general-072007-sector-construccin/6a45792cde3c6003da189ff1 - DGII legal basis for the 2% transfer withholding: https://ayuda.dgii.gov.do/conversations/discusiones/base-legal-retencion-2-transferencia-de-titulos-y-propiedades/5f6355928cd858ce872bb35a - Ministry clarification on the specific foreign technology and royalty categories: https://www.hacienda.gob.do/ley-30-26-no-dispone-impuestos-por-suscripciones-de-ciudadanos-a-plataformas-digitales-reduce-de-27-a-15-la-retencion-a-empresas-que-contratan-servicios-tecnologicos-en-el-exterior/ Legal basis cited by DGII: Law 11-92, article 309, as amended by Law 30-26, article 17; Regulation of Title II of the Tax Code, article 70. ## Validation - The branch is rebased on the current 17.0 head and contains one squashed commit. - The account, tax-template, and fiscal-position CSV files have consistent column counts, unique IDs, and valid child/account references. - A fresh Dominican chart contains only the new current-rate IDs; the superseded template IDs are absent. - The fresh chart was verified with fees/rentals at 15%; General Rule 07-2007 at 3% on `21030308`; Article 70(a)/(b) at 3% on `21030309`; transfers at 2% on `21030306`; general remittances at 27% on `21030307`; and the covered foreign categories at 15% on `21030310`. - The 15% services and 3% construction groups contain exactly the current tax children, and the new services fiscal position maps each purchase tax to only the 15% group. - An existing company loaded from the pre-law template was reloaded twice. Its historical 10%/10%/2% taxes, historical groups, and historical fiscal position retained their original record IDs and configuration; all current records were created once; the old and new positions each retained exactly two isolated mappings; and the second reload was idempotent. - `/account:TestChartTemplate`: 22 tests passed, 0 failures, 0 errors. This is the first contribution by Grupo de Consultoria Henca (https://www.consultoriahenca.com); the corporate CLA signature is included in `doc/cla/corporate/consultoriahenca.md` as instructed by `doc/cla/sign-cla.md`. Forward-Port-Of: odoo/odoo#280127 Forward-Port-Of: odoo/odoo#275986
The warning shown when users try to edit properties before a required product category or definition is set now explains the real problem instead of showing "undefined". This helps users understand what must be completed first and reduces confusion during product setup.
Original PR description
Versions -------- - saas-18.3+ Steps ----- 1. Create a new product without a category; 2. try to edit properties. Issue ----- You get the following warning notification: > Oops! You cannot edit the Product Category "undefined". > [!note] > If `account_asset` is installed, the warning will remain empty until https://github.com/odoo/enterprise/pull/94583 is merged. Solution -------- The property cannot be edited because the definition record doesn't have a value. By checking if `this.defenitionRecordId` is unset, we can display a clearer warning message that the field has to be defined first. opw-4980006
This fixes an issue where users could not update line descriptions on confirmed purchase orders when the product column was visible. The change makes description editing consistent across purchase order views, reducing confusion and avoiding unnecessary workarounds.
Original PR description
Steps to reproduce the bug: - Create and Confirm a purchase order with any product and a description (name) on the order line - Try to edit the description (name) field Problem: The description field…
Steps to reproduce the bug:
- Create and Confirm a purchase order with any product and a description (name) on the order line
- Try to edit the description (name) field
Problem:
The description field was not editable on a confirmed purchase order when the product_id column was visible, but became editable when product_id was hidden.
The `ProductLabelSectionAndNoteField` widget renders both `product_id` and the description (`name`) in a single cell. When `props.readonly` is true (because `product_id` has `readonly="state in ('purchase', 'to approve', 'done', 'cancel')"`) and the order state is not draft (`isProductClickable` is true), the template rendered the description textarea with a hardcoded `readonly="1"` attribute, making it impossible to edit regardless of the actual intended readonly state for the description.
When `product_id` was column-invisible, the `name` field rendered via its own `section_and_note_text` widget, which correctly used `sectionAndNoteIsReadonly` (blocking only `cancel`, `done`, `posted`) hence the inconsistency.
Solution:
Replace `readonly="1"` with `t-att-readonly="sectionAndNoteIsReadonly"` on the description textarea so its editability follows the same logic as the other cases: blocked only for terminal states (`cancel`, `done`, `posted`), not for `purchase` or `to approve`.
opw-5474986
Forward-Port-Of: odoo/odoo#272102Kitchen orders in setups with fewer than three stages now record completion time based only on preparation time. This prevents inflated timing data when staff complete multiple order lines one by one, improving the accuracy of kitchen performance reporting.
Original PR description
Kitchens with fewer than 3 stages were incorrectly recording both preparation and service time. Completion time should only include preparation time in this case. Steps to reproduce: - Configure the kitchen to have only 2 stages - Create an order with more than 1 order line - Mark the order lines as completed one by one - Observe that the completion time is calculated incorrectly opw-6515078
Fresh databases without demo data now correctly prepare the accounting dashboard setup for the default company. This prevents an error when users open Tax Returns, making first-time accounting setup smoother and more reliable.
Original PR description
Steps to reproduce: 1. Create a new DB without demo data. 2. Go to Accounting Dashboard. 3. Click on the 'Tax Returns' card. 4. Input the date and click 'Apply'. Before: Since saas-18.3, the…
Steps to reproduce: 1. Create a new DB without demo data. 2. Go to Accounting Dashboard. 3. Click on the 'Tax Returns' card. 4. Input the date and click 'Apply'. Before: Since saas-18.3, the post-init hook only iterated over companies with a chart_template defined. In databases created without demo data, the default company had no chart_template set at post-init, so `_initiate_account_onboardings()` was never called. This prevented the creation of an `onboarding.progress` record for the accounting dashboard. When clicking the 'Tax Returns' button, it attempted to access the onboarding progress but found none, raising a `ValueError: Expected singleton`. After: We now iterate over all companies and only guard `_get_tax_closing_journal()` behind the chart_template check. This ensures that even companies without a localization chart template (such as the default company in a fresh database without demo data) will have their onboarding progress correctly initialized, avoiding the crash on the accounting dashboard Tax Return button.
This fix prevents chart legend clicks from accidentally opening linked dashboard menus. It also makes middle-click behavior consistent when users click directly on chart elements, reducing confusion when working with spreadsheet dashboards.
Original PR description
### [FIX] charts: avoid conflicting click listeners We have several click listeners on charts: one on the legend, one on all odoo chart elements, and one on the chart itself in dashboard. The first…
### [FIX] charts: avoid conflicting click listeners We have several click listeners on charts: one on the legend, one on all odoo chart elements, and one on the chart itself in dashboard. The first two are handled in ChartJS, and the last one is handled in a `t-on-click`. The problem is that the `t-on-click` was called for every click on the chart, even if the click was on the legend. This is because ChartJS handles events at the next animation frame, so the `t-on-click` was always called before the ChartJS click listener. To fix this, we also handle the click on the chart inside ChartJS. The middle mouse click was also handled when clicking on the chart to open its linked menu, but not when clicking on an element of the chart(eg. bar of odoo bar chart) chart. Task: [4636147](https://www.odoo.com/web#id=4636147&cids=1&menu_id=4720&action=333&active_id=2328&model=project.task&view_type=form) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
New company cars created through the Belgian Salary Configurator will no longer have the “Make vehicle available” option selected automatically. This prevents cars ordered for incoming employees from being incorrectly treated as available in Fleet, reducing confusion and manual correction.
Original PR description
Steps to reproduce: - Install the Salary Configurator (Belgium) module - Create a new offer in the recruitment process. - Open the salary configurator and select a company car to order. - Fill in all other necessary details and sign the contract. - Navigate to the fleet module and locate the newly created car for new employee Issue - The "Make vehicle available" checkbox is incorrectly checked by default for the newly created company car. Reason: - The create method contains code that writes values for plan_to_change_bike and plan_to_change_car, which causes the 'Make vehicle Available' to be checked Solution - Remove the code that writes to plan_to_change_bike and plan_to_change_car in the create method to prevent the vehicle from being marked available by default. task-4868865
This fix prevents automated tests from unpredictably changing user session data during login checks. It keeps test runs more stable and reduces false failures, without changing normal customer-facing behavior.
Original PR description
The test harness patches the CryptContext object to spend less time hashing to decrease total test runtime. Because the hash parameters have changed, every first login (per transaction) per user will result in a hash rotation. The session_id is also rotated when the password hash rotates. When multiple requests are sent to the server while a session rotation is underway, the session datastore holds either a valid, or expired, or logged-out user session. This is a source of indeterminism in tests that can be prevented by always returning None value for replacement hash. REF Runbot; https://runbot.odoo.com/odoo/error/242811 REF Runbot; https://runbot.odoo.com/odoo/error/233722 Forward-Port-Of: odoo/odoo#285710
This update addresses a problem in the Spreadsheet area to improve how the spreadsheet interface behaves or appears. It helps provide a smoother and more reliable experience for users working with spreadsheets in Odoo.
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 adjusts the Spreadsheet app’s front-end files to support a testing-related fix. It helps improve reliability around spreadsheet behavior without introducing a major user-facing change.
Original PR description
--- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Full-width website headers and eCommerce shop pages now use the same spacing rules on large screens. This removes visible misalignment between headers, content, snippets, and shop layouts, creating a more polished storefront experience.
Original PR description
The website header fullwidth option and the eCommerce shop content fullwidth option were merged at different times and currently behave differently on large screens, causing noticeable misalignment…
The website header fullwidth option and the eCommerce shop content fullwidth option were merged at different times and currently behave differently on large screens, causing noticeable misalignment between the header and content. The header option only applies a container-fluid class, while the shop option goes further by adjusting padding for XL to prevent content from appearing too "stuck" to the edges of the screen. When both options are active, this creates visual inconsistency. Furthermore, since website_sale had its own container-fluid padding logic while the rest of the website handled it differently, this led to inconsistencies. This commit establishes a consistent container-fluid padding system across the entire website that applies to headers, snippets, page layouts, and any other components using container-fluid class. It also updates (in website_sale) some conditional sidebar padding logic to handle presence/absence of sidebar, removes unnecessary container padding, and refines variables for better maintainability. The solution provides unified spacing behavior whether container-fluid (fullwidth option) is used in headers, eCommerce layouts, snippet content, or page layout, eliminating visual inconsistencies. task-4840034 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update corrects how spreadsheet pivot tokens are handled, helping spreadsheet views work more reliably. It affects the Spreadsheet app interface and styling, with a limited user-facing impact focused on preventing a specific issue.
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
Members can now use AI-generated field content when prompts include custom Studio fields, without being blocked by an email template editor permission error. This makes AI field assistance behave consistently for both standard and custom fields.
Original PR description
Description of the issue/feature this PR addresses: 'Member' users can use the AI field button when the prompt contains standard field references. When the prompt contains a Studio field reference,…
Description of the issue/feature this PR addresses: 'Member' users can use the AI field button when the prompt contains standard field references. When the prompt contains a Studio field reference, there is an error message stating 'email template editor' access is required. Current behavior before PR: -Create an internal 'Member' user -Add a 'user' group for the app you want to test on (bug spotted in Helpdesk). -Make a plain text Studio field -Make a text AI field where the prompt references the plain text Studio field you just created. -Make a text AI field where the prompt references a standard available field. -Log into the database as the 'Member' user -Push the 'AI' button on each of the two fields you created. -The one referencing the standard field should populate as normal; the one referencing the Studio field will trigger an error message asking for 'Email template editor access'. Desired behavior after PR is merged: Allowing AI fields unrestricted rendering to avoid the access error when the studio field is used in the prompt. Task-5016767 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a live chat issue where operators could not leave a conversation after the visitor had already left. Ended chats are now properly marked as read, so the interface shows the leave option instead of an unread badge.
Original PR description
**Current behavior before PR:** When an operator accessed a live chat where the visitor had left, the composer was disabled, preventing `markAsRead()` from executing and showing the unread message counter badge instead of the leave action. **Desired behavior after PR is merged:** `markAsRead()` is now called on ended live chat, ensuring that operator can leave the channel. **Task**-4500402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fix prevents accounting reports from being incorrectly nested inside other report sections during upgrades or configuration changes. It helps keep custom financial reports organized correctly and avoids confusing duplicated or nested report structures for users.
Original PR description
Case: - Custom report has sections and is not root - Root report is added as a section to another report. For example here: https://github.com/odoo/enterprise/blob/saas-18.3/account_reports/data/annual_statements.xml#L8 Example before the upgrade to 18.3: ``` yaih@(none):yaih_3038736> SELECT ar.id FROM account_report ar JOIN ir_model_data imd ON imd.res_id = ar.root_report_id where imd.name = 'balance_sheet' +----+ | id | |----| | 26 | | 21 | +----+ SELECT 2 Time: 0.009s yaih@(none):yaih_3038736> SELECT * FROM account_report_section_rel +----------------+---------------+ | main_report_id | sub_report_id | |----------------+---------------| | 26 | 21 | | 26 | 20 | +----------------+---------------+ ```
Turkish e-Ledger exports now fill in line numbers automatically and keep the numbering continuous across the full fiscal period. This helps monthly filings match GIB expectations and avoids manual corrections after export.
Original PR description
Before: the `LineNumber` column of the e-Ledger CSV was always empty, left to be filled after the export. Since the ledger is filed monthly, whatever filled it restarted at 1 every month, while GİB expects the numbering to start once, at the beginning of the fiscal period, and to run unbroken until its end. Now: the column is written by the export. An export starting after the first day of the fiscal period is offset by the number of rows that period already counts, so February continues where January stopped, and a full-year export numbers the same rows identically. The lines are also read in ascending date order. They were sorted by the default order of `account.move.line`, the most recent first, so the first row of the file was the last entry of the period and could not be numbered 1. This reverses `EntryNumberCounter` as well, which now counts from the oldest entry. task-6424730 Forward-Port-Of: odoo/enterprise#130486 Forward-Port-Of: odoo/enterprise#127518
Point of Sale users can now open the app without running into an access error when an optional installation request component is not installed. This prevents unnecessary disruption for employees who have Point of Sale permissions but do not have administrator settings access.
Original PR description
Fixes https://github.com/odoo/odoo/issues/238503 Avoid access error if `base_install_request` is not installed Example use case: - Install point_of_sale (without having `base_install_request` installed) - Give user Marc Demo Point of Point of Sale permission but NOT Administration > Settings - Go to Point of Sale ``` Access Error You are not allowed to access 'Module' (ir.module.module) records. This operation is allowed for the following groups: - Administration/Settings Contact your administrator to request access if necessary ``` Please @pedrobaeza and @christian-ramos-tecnativa can you review it? @Tecnativa TT57146 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#240587
This fixes issues introduced during a previous code update that could affect expense filtering and employee lookup in the organization chart. The change helps ensure employees and managers see the correct expense records and that the org chart continues to load employee information properly.
Original PR description
Due to guilty lack of tests, fw-port PR odoo/odoo#279530 was merged with errors. - `_search_filter_for_expense` domains fix. - `_check_employee` was renamed to `_get_employee`
Users can now open their Discuss inbox and history even when a notification refers to a business record that has since been deleted. This prevents an error message from blocking access to mailbox content and keeps older notifications viewable where possible.
Original PR description
Before this commit, when a message notification from inbox or history has its related record deleted, the user couldn't load inbox or history. Steps to reproduce: - Have mitchell admin receive…
Before this commit, when a message notification from inbox or history has its related record deleted, the user couldn't load inbox or history. Steps to reproduce: - Have mitchell admin receive notification in Odoo - Install `mail_group` - Wait a few seconds to receive following user_notification from mail group: ``` on My Company News Hello, You have messages to moderate, please go for the proceedings. ``` - Go to related record then delete it - Go back to inbox or history => One of them show `An error occurred while fetching messages.` This happens because the related record is not a `mail.thread`, but still creates some `mail.message` to send user notifications. `mail.thread` cascade delete the messages in message list, but threadless records do not. Because the related record is deleted, these messages are attempted to be displayed in mailbox, but due to related record having no `display_name` by non-existing, the fetch data of inbox/history crashes with: ``` MissingError: Record does not exist or has been deleted ``` This commit fixes the issue by doing its best to show message even when the related record has been deleted. opw-4546920
This update ensures demo Drawer and Flipover products receive the required lot numbering setup when inventory-related demo data is installed. It prevents an error during receipt validation, so users can generate serial or lot numbers for these products without interruption.
Original PR description
Issue before this commit: ========================= When generating a lot number for a Drawer/Flipover and validating the operation, a traceback is raised: "ValueError: Expected singleton:…
Issue before this commit: ========================= When generating a lot number for a Drawer/Flipover and validating the operation, a traceback is raised: "ValueError: Expected singleton: ir.sequence()" Steps to Reproduce: ========================= - Install the "stock" module. - Create a receipt for the drawer product. - Open the detailed operations wizard. - Click on "Generate Serials/Lots". - Enter the first lot/serial number. Validate it. Result: A traceback is raised with: ValueError: Expected singleton: ir.sequence() Cause of the issue: ========================= The 'lot_sequence_id' field is defined in the 'stock' module with a default value. However, defaults are only applied at record creation time. When the drawer is initially created by the product module, the lot_sequence_id field does not exist yet. Later, when the stock module is installed, the existing drawer is configured to be tracked by lot via demo data. Since the drawer already exists, the default value for lot_sequence_id is not applied, leaving the field unset. The lot_sequence_id field is added in this [PR](https://github.com/odoo/odoo/pull/200395), but the issue occurs on [the line](https://github.com/odoo/odoo/blob/saas-18.3/addons/stock/models/stock_move.py#L1026) introduced in [this PR](https://github.com/odoo/odoo/pull/240368). The code attempts to call get_next_char() on lot_sequence_id while it is still unset (False), resulting in the method being called on an empty recordset. As a result, serial/lot number generation fails due to a missing sequence. Same issue for Flipover. With This Commit: ========================= Ensure that the existing drawer product tracked by lot is assigned a default lot_sequence_id when the stock module is installed. This guarantees consistent and correct lot generation for the drawer/Flipover.
Livechat users who do not have payroll access can now view needed employee-related information without running into access errors. The change uses employee public records where appropriate, improving reliability for internal livechat workflows while preserving existing access restrictions.
Original PR description
Some users have access to livechat but not to payroll, which leads to access errors when fetching employee-related data. To avoid this issue, employee public IDs are used instead, as they are accessible to all internal users without requiring payroll access. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes an issue where keyboard shortcuts could apply formatting to parts of a page that are not meant to support rich text editing, even though the toolbar was disabled. It helps keep blog header and footer content consistent and prevents accidental styling changes in restricted fields.
Original PR description
Problem: Selecting text in non-html fields disables toolbar formatting, but pressing CTRL+B still formats the text. Cause: `formatSelection` did not check if the selection was inside a non-html field before applying formats. Solution: Return early in `formatSelection` if the selection is inside a non-html model field element. Steps to reproduce: 1. Go to /blog and open an article. 2. Open editor and select header/footer text. 3. Press CTRL+B. => Selected text becomes bold. opw-6537402 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#286675
This fix ensures the alternative mode labels in the AI Copywriter dialog are shown in the user's selected language. It improves consistency for multilingual users and makes the writing assistant easier to use outside English.
Original PR description
Description of the issue/feature this PR addresses: The alternativemodes on the AI Copywriter dialog are not translated Current behavior before PR: <img width="1079" height="250" alt="image" src="https://github.com/user-attachments/assets/fced9432-b557-44de-9b7c-a31547b7a16b" /> Desired behavior after PR is merged: <img width="1078" height="250" alt="image" src="https://github.com/user-attachments/assets/1499836a-924e-425c-b328-27a378eae62a" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#230740
This fix prevents outdated activity information from being reused when a user returns to an older browser tab. It also preserves rich text formatting in activity-related content, helping avoid incorrect names, avatars, or visible HTML text in the interface.
Original PR description
1. record.toData() keeps markup of html fields Before this commit, `record.toData()` was not retrieving the "markup" flag of html fields. This is a problem because inserting this data would remove…
1. record.toData() keeps markup of html fields Before this commit, `record.toData()` was not retrieving the "markup" flag of html fields. This is a problem because inserting this data would remove the `Markup` of these html fields, therefore showing html as text content in UI. This commit fixes the issue by having `record.toData()` return `["markup", string]` rather than `string` on html fields that have markup content, so that insert preserves the markup. 2. broadcasted activity data is time-limited When an activity has updated content in a tab, the activity data is broadcasted to all other tabs. Before this commit, the broadcasted data was taken into account to other tabs, even if other tabs woke up much later. This is a problem because tabs would feed old activity data, which leads to wrong discuss state. For example, the assignee of activity is also broadcasted to display avatar and name, and the assignee of activity may have outdated data like different name. This commit fixes the issue by limiting the broadcasted activity data to other tabs in time to 3 seconds, so that other tabs do not feed from outdated data.
Receipts now continue to show next-order loyalty coupons even after the point of sale page is refreshed or data is reloaded. This prevents staff from reprinting incomplete receipts and helps customers retain the discounts they earned for future purchases.
Original PR description
Step to reproduce: = - Complete order with Next order coupon - Open Order and print receipt (This time coupon is visible) - Refresh page Or Reload Data - Same order > Print receipt Issue: = - Next time on-wards next order coupon will not shown on the receipt. Reason: = - Loyalty program data is stored in the uistate which destroyed on refresh page OR reload data. Fix: = - Fetched data from the server when uistate doent have any loyalty program data for that order while receipt printing only. task-5890998 related pr: https://github.com/odoo/enterprise/pull/128730 Forward-Port-Of: odoo/odoo#247127
A typo in the Helpdesk “Auto Assignment” group name was corrected. This improves clarity for users and administrators when viewing or managing Helpdesk settings.
Original PR description
This commit fixes the typo in the "Auto Assignment" group. task-6542450 Forward-Port-Of: odoo/enterprise#130841
Combo meals with added extras now keep the correct total when the order is sent to payment and saved in the backend. This prevents incorrect totals and negative order lines for restaurant self-order purchases.
Original PR description
**Steps to reproduce:** - Order a combo with some extra products - The displayed total will be correct - Go in the restaurant or the orders in the backend - The total is not correct, some lines are…
**Steps to reproduce:** - Order a combo with some extra products - The displayed total will be correct - Go in the restaurant or the orders in the backend - The total is not correct, some lines are in negative **Problem:** When ordering a combo in the self order, the displayed price will be correct, up until the payment where it is recomputed wrongly. This also affects the backend as this is the value that is used to save the order's price. **Why the fix:** In the frontend, everything is correctly computed, explaining why the correct price is displayed. But when going back to the backend to retrieve some data and to make sure that the product prices did not change, the data is wrongly computed. The _verify_line_price function is the one that changes the data. This arises when we order some extras in the combo, so it seems the function was not changed when the combo's REF was done. This fix was made by keeping the implemented logic to distribute the unit_price among the lines as it was done before, so it might be different from what is done in the frontend, but this is how it was done even before the combo's REF. opw-4990886
Users can now reliably remove text or background colors even when the color was applied higher up in the content structure, such as in lists, buttons, or table cells. This makes the formatting toolbar behave correctly and reduces frustration when cleaning up styled content.
Original PR description
#### Description of the issue this PR addresses: - Color detection only checked the closest element of the selected text nodes, assuming the color is always applied on their direct parent. - This is…
#### Description of the issue this PR addresses: - Color detection only checked the closest element of the selected text nodes, assuming the color is always applied on their direct parent. - This is not always the case: the color can be applied on a `<font>` wrapping an inline element (e.g. a neutral style `<span>` created inside button links), or on the list item itself when its content is wrapped in a block (e.g. a heading). - As a result, remove format could not remove such colors, and its toolbar button stayed disabled as no color was detected for the selection. #### Desired behavior after PR is merged: - Introduce the `closestColoredElement` util, which returns the element actually applying the color to a node by looking up its ancestors. - The lookup stops on an element resetting the color of its content (`style="color: initial"`), as there is nothing to remove above it. It is also limited to the closest paragraph related element, or to the closest list item (color) or table cell (background color), as those can hold the color of a text nested deeper in them. - Use it for the remove format detection, and to get the `<font>` to clean when removing a color: the closest one is not necessarily the one applying it, e.g. a `<font>` with a background color nested in a `<font>` with a text color. task-6312677 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Demo products used in helpdesk stock and rental flows now receive the needed lot/serial number sequence when their demo data is installed. This prevents an error when users generate and validate serial or lot numbers for products like Cabinet with Doors or Printer.
Original PR description
Issue before this commit: ========================= When generating a lot number for a Cabinet with Doors/Printer and validating the operation, a traceback is raised: "ValueError: Expected singleton:…
Issue before this commit: ========================= When generating a lot number for a Cabinet with Doors/Printer and validating the operation, a traceback is raised: "ValueError: Expected singleton: ir.sequence()" Steps to Reproduce: ========================= - Install the "helpdesk_stock" module. - Create a receipt for the Cabinet with Doors product. - Open the detailed operations wizard. - Click on "Generate Serials/Lots". - Enter the first lot/serial number. Validate it. Result: A traceback is raised with: ValueError: Expected singleton: ir.sequence() Cause of the issue: ========================= The 'lot_sequence_id' field is defined in the 'stock' module with a default value. However, defaults are only applied at record creation time. When the Cabinet with Doors is initially created by the product module, the lot_sequence_id field does not exist yet. Later, when the helpdesk_stock module is installed, the existing Cabinet with Doors is configured to be tracked by lot/serial via demo data. Since the Cabinet with Doors already exists, the default value for lot_sequence_id is not applied, leaving the field unset. The lot_sequence_id field is added in this [PR](https://github.com/odoo/odoo/pull/200395), but the issue occurs on [the line](https://github.com/odoo/odoo/blob/saas-18.3/addons/stock/models/stock_move.py#L1026) introduced in [this PR](https://github.com/odoo/odoo/pull/240368). The code attempts to call get_next_char() on lot_sequence_id while it is still unset (False), resulting in the method being called on an empty recordset. As a result, serial/lot number generation fails due to a missing sequence. Same issue for the printer. With This Commit: ========================= Ensure that the existing Cabinet with Doors/Printer product, tracked by serial/lot is assigned a default lot_sequence_id when the helpdesk_stock module is installed. This guarantees consistent and correct lot generation for the drawer.
The Planning schedule email template now shows the “View Your Planning” button with a default color when viewed in read-only mode. This makes the call-to-action clear in template previews while still allowing company-specific colors to apply when emails are sent.
Original PR description
Steps to reproduce: - Install Planning - Open email templates - Open Planning New Schedule template Issue: - `View Your Planning` button doesnt have any color and doesnt seem like a button. Cause: - Earlier the colors we hard-coded, now they are applied dynamically using button color set on company settings. - As t-attf is evaluated during read-only render we are not able to see the color. Fix: - Set default color of button as Purple to be visible in read-only mode. - Have dynamically added colors override default colors using `!important`. task-5064862
After validating an OTP during GSTR1 submission, the confirmation wizard now closes automatically. This removes an unnecessary manual step and makes the GST filing flow smoother for users.
Original PR description
Steps to Reproduce: 1. Open the GST Return Period page 2. Click on Push to GSTN 3. Re-initiate → Send OTP → Validate OTP Issue: - After OTP validation, the wizard does not close automatically. Root Cause: - The method button_send_gstr1 and action_get_irn_data were returning 'type': 'ir.actions.client' instead of 'type': 'ir.actions.act_window_close'. Fix: - Updated the button_send_gstr1 and action_get_irn_data methods to return 'type': 'ir.actions.act_window_close' to ensure the wizard closes properly after OTP validation.
A product used in a Mexican point-of-sale refund test is now marked as available for POS, so it appears correctly when paid orders are loaded. This keeps the refund discount scenario reliable and prevents false test failures.
Original PR description
Before this commit: * `available_in_pos` was not set on the product in the test, causing it to be missing from the ticket screen when fetching paid orders using `callRelated`. After this commit: * Set `available_in_pos` on the product so it is loaded correctly and appears in the ticket screen when fetching paid orders, fixes test case `test_mx_pos_refund_discount_order`. task-5890998 related pr: https://github.com/odoo/odoo/pull/247127 Forward-Port-Of: odoo/enterprise#128730
SEPA Direct Debit export files no longer include an extra identifier field for countries where banks may reject it, such as Italy. The field is now kept only for Nordea countries that explicitly require it, reducing failed payment file submissions.
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
This fix makes an internal time off accrual test use fixed dates instead of dates based on the day the test runs. It prevents false test failures when the calculated date falls on a non-working day, improving release reliability without changing employee-facing behavior.
Original PR description
## Before: The test relied on relative dates (today + 2 days) when creating a leave request. The behavior depended on the day it was executed. For example, if the test ran on a Friday, the leave request would be created for Sunday, causing the validation to fail because the employee was not supposed to work on that day. ## After: This uses a static date for both the accrual allocation and creating the leave to avoid unnecessary errors. runbot-945745 Forward-Port-Of: odoo/odoo#282190