Monday, August 24, 2026
99 changes · master
New functionality added to Odoo
Belgian payroll now supports the NSSO deduction for subsidized contract workers and includes it in DMFA reporting. This helps employers calculate the monthly deduction and report the totals per employee more accurately in the payroll declaration.
Original PR description
Implements the NSSO subsidized contract workers deduction (ACS) and DMFA reporting - New salary rule for montly deduction computation. - New method `_is_eligible_for_acs_deduction` on `hr.version` to check eligibility. - Moving mu and deduction 3000 computation to `L10n_BeDmfa` class methods. - New model `l10n_be.dmfa.acs.reduction.line` storing total deduction per employee per dmfa. - Dedicated tab on DMFA form view. - Deduction computation and display on DMFA report using target group deduction. Task:6173205
Odoo now supports SSLCOMMERZ as a payment provider, enabling businesses to accept payments through a wider range of Bangladesh-focused payment methods. This helps merchants expand checkout options for customers and improve local payment coverage.
Original PR description
Add new payment provider SSLCOMMERZ. See [README.md](https://github.com/odoo/odoo/pull/269048/changes#diff-333c96a43e8bf18f5ce4df34664d8eaa8f195afabbcdca2bfa6fc016d00b26ea) for more details. task-6185518
Enhancements to existing features
Time off administrators can now see and configure whether each time off type creates a matching Calendar entry. This makes the existing setting easier to find and helps businesses control when leave requests appear in employees' calendars.
Original PR description
The `create_calendar_meeting` field on `hr.leave.type` allows users to choose if leave requests created with a given time off type generate a corresponding entry in the Calendar app. However, this field was not displayed on the form view. This commit adds `create_calendar_meeting` to the `hr.leave.type` form view inside the configuration section, along with dedicated help text explaining its behavior. Task: 6445794 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283450
Resolved issues and error corrections
Cancelling the product configurator in Point of Sale no longer shows optional products for an item that was not added. This prevents cashiers from being prompted to add extras for a discarded product, reducing confusion during checkout.
Original PR description
When discarding the product configurator, we still showed the optional product. We no longer do that as no one wants to add optional products to a not-added product. task-6442422 Forward-Port-Of: odoo/odoo#283378 Forward-Port-Of: odoo/odoo#282916
Features or functions removed from Odoo
Odoo removed a temporary icon compatibility layer that supported legacy FontAwesome markup after the system completed its move to the newer icon format. This reduces maintenance overhead and keeps the web and editor code cleaner, with safeguards already in place to prevent old icon usage from returning.
Original PR description
__What__ - Remove `icons_mappings/fa_to_ms.scss` and `icons_mappings/oi_to_ms.scss`, along with every `.fa`/`.fa-*` compatibility rule in `icons.scss`. - Remove `LegacyIconMigrationPlugin` (and its…
__What__ - Remove `icons_mappings/fa_to_ms.scss` and `icons_mappings/oi_to_ms.scss`, along with every `.fa`/`.fa-*` compatibility rule in `icons.scss`. - Remove `LegacyIconMigrationPlugin` (and its tests), which rewrote legacy `fa fa-*` markup into `oi` + `data-icon` at editor startup. __Why__ The mappings only existed as a transition layer: they let old `fa-*` markup keep rendering while the codebase was being converted. That transition is over. - odoo/odoo#256840 converted every remaining `fa-*` usage to `oi` + `data-icon`, so nothing relies on the mapping anymore. - odoo/odoo#279361 added a CI check preventing any new `fa-*` class from being introduced, so the mapping cannot become needed again. __Note__ `icons.scss` was cleaned up along the way: the now single-purpose mixins (`icon-content`, `ms-icon`, `oi-icon`, `rotate`, `flip`) were inlined, duplicated blocks (`.oi-fw`, `.oi-spin`, `.oi-pulse`, the variables section) were deduplicated, the RTL rules were collapsed into a single selector list, and the `-webkit-` prefixed transforms/animations were dropped. The `fa-spin` keyframes are renamed `oi-spin` since the FontAwesome ones are no longer inherited. task-5901783
Code cleanup and technical improvements
This update removes redundant invoice code that no longer performed any useful work. It helps keep the GCC invoicing module simpler and easier to maintain without changing how users create or view invoices.
Original PR description
Remove create() and _compute_narration() method overrides from l10n_gcc_invoice as they only existed to call _load_narration_translation(), which has already been disabled. The parent class implementations handle all required functionality. Keeps the codebase clean by removing unnecessary method overrides. Forward-Port-Of: odoo/odoo#281565 Forward-Port-Of: odoo/odoo#281395
Documentation and clarification updates
This update records that GitHub user kshitij-nariya has signed Odoo's Individual Contributor License Agreement. It ensures their future contributions can be reviewed and merged without legal approval blockers.
Original PR description
Description of the issue/feature this PR addresses: Signed the Odoo Individual Contributor License Agreement to contribute to the Odoo repository. Current behaviour before PR: The CLA signature is missing for GitHub user `kshitij-nariya`, which will prevent future contributions from being accepted and merged. Desired behaviour after PR is merged: The CLA signature for `kshitij-nariya` is recorded in the repository, allowing future pull requests and contributions to be successfully merged. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282808
In editable lists configured to add new rows at the top, the “Add a line” button now appears at the top as well. This makes it clearer where new entries will be inserted and improves consistency across related sales, stock, project, and general list views.
Original PR description
Previously, when using editable="top", clicking "Add a line" created the new record at the top, but the "Add a line" button is at the bottom of the list, making the UI inconsistent. After this change, the "Add a line" button is positioned at the top of the list, and new records are inserted directly below it. This makes it clearer where new lines will be created and provides a more intuitive editing experience. task-6234437 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This change lets Odoo population scenarios combine several reusable data blueprints instead of copying the same setup repeatedly. It makes demo, benchmark, and test data easier to maintain across areas like accounting, sales, stock, products, and projects while reducing inconsistencies when shared datasets change.
Original PR description
Population scenarios often reuse independent datasets, such as a product catalog, partners, or warehouses. Blueprint inheritance can extend one definition, but it cannot combine several definitions into a new scenario. This currently requires copying operations between blueprints, making them harder to maintain and reuse. Add an `<import>` element that expands another XML blueprint in place. Imports can be customized through XPath specifications and namespaced to avoid ID conflicts, including when the same blueprint is imported more than once. task-6314573 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Grouped list counts are moved back next to the group name after earlier design experiments proved less suitable. This restores a more familiar layout while keeping subtle visual improvements to group header spacing and background color.
Original PR description
After some experiments with the position and design of the grouped list Count, it has been decided to revert its position, ie: next to the group name. The previous redesigns (#235250 #255332 #266360) were reverted. Only some changes on the group header height and bg color were added back from #235250. task-6452702 part-of: task-5221260
This update enables stricter automated quality checks for project-related document test code. It helps keep the codebase more reliable while limiting user-facing changes to a minor adjustment in how a project menu option is evaluated.
Original PR description
Task-5180137 Forward-Port-Of: odoo/odoo#284055 Forward-Port-Of: odoo/odoo#280233
Sales teams can now configure products directly inside quotation templates, including attribute choices, custom values, and optional extras. This makes reusable quote templates more accurate and reduces manual rework when creating customer quotations.
Original PR description
Before this commit: Quotation template lines only stored a product variant (product_id), with no support for no-variant attributes, custom attribute values, or the product configurator dialog. After this commit: Quotation template lines can now use the product configurator, just like regular sale order lines like pick attribute values, custom values, and extra options directly when adding a product to a template. - Prices are hidden in the configurator for templates, including for optional lines. - Matrix/grid-configured products open the regular configurator dialog on templates. - Attribute selections carry over in both directions from a template into a new quotation, and from a quotation line back into a template. - Template description translations stay in sync across languages. task-6128596
This update refreshes U.S. payroll tax settings for Kentucky, Utah, and Kansas so payroll calculations align with corrected 2026 state requirements. It updates unemployment wage caps, Utah withholding table values, and Kansas allowance handling to help ensure more accurate employee pay and tax withholding.
Original PR description
Purpose: Some values and data need to be updated as a follow-up to this PR: https://github.com/odoo/enterprise/pull/125937. Kentucky: - 2026 SUI cap = 12,000 Utah: - 2026 SUI cap = 50,700 - Allowance and threshold tables values for single are corrected to be 2 and 36 respectively. Kansas: - Income tax formula for Kansas already includes the filer and/or spouse in the allowances. Correct the formula to only apply the allowance to the dependents. task-6467500
Users can again access document folder actions from menus, making it easier to share or export live folder views into spreadsheets and knowledge articles. The update also improves linked and embedded folder sharing while protecting access tokens from being exposed through Knowledge search state.
Original PR description
Also impacted: test_documents_full It is convenient to export a dynamic view of a folder in both spreadsheet and knowledge links settings. * Care is taken to avoid leaking access folders tokens through the search panel/model's state in knowledge. * We also enable sharing folders shared via link through embedded views as it enables benefitting from the power of them vs. adding the link to the folder in the article. * As with other actions initiated on shortcuts, the "real" operation is done on the target. Sharing the target is simpler than patching a folder "child_of" to return the target children (shortcut as documents_unique_folder_id is not supported). Task-5180137 Forward-Port-Of: odoo/enterprise#128882 Forward-Port-Of: odoo/enterprise#122481
New employee payroll review records now start in the reviewed status instead of an empty status. This removes ambiguity in employee payroll setup and keeps review indicators clearer for payroll and accounting teams.
Original PR description
Default the field to '1_reviewed' task-6470096
Website editors can now place content in dedicated areas on product pages, choosing whether it appears on every product page or only on the current one. Terms and conditions content is moved into the new editing area automatically, and empty placeholder lines are cleaned up to prevent unwanted spacing.
Original PR description
This commit adds different drop zones on the product page. We introduce zones where elements dropped inside will be displayed across all product pages, as well as zones where elements dropped inside will only be visible on the current product page. We also remove the terms and conditions option from the edit settings, and thanks to the upgrade script, we move them to the new dropzone if the option was enabled. If a page with the `o_drop_inner_empty` class is saved and contains an empty `<p>` tag, we remove it to avoid unwanted whitespace. Currently, a hint is displayed, but there is no way to delete the empty line. Upgrade PR: https://github.com/odoo/upgrade/pull/10116 task-6147939
Activity assignment emails are now grouped so a user receives one message per record instead of separate emails for every activity. This reduces inbox clutter and mail server load, while also ensuring scheduled activities use a valid compatible activity type.
Original PR description
Previously, when a plan scheduled multiple activities assigned to a user, the system sent a separate email notification for each individual activity. This resulted in excessive email spam for the…
Previously, when a plan scheduled multiple activities assigned to a user, the system sent a separate email notification for each individual activity. This resulted in excessive email spam for the assignee and unnecessarily increased mail server costs.
This commit improves the mail notification flow by grouping activities by user and record before dispatching. Instead of sending one email per activity, it now sends a single consolidated email per user per record, listing all assigned activities with their summaries and deadlines.
[IMP] {test_}mail: ensure activity type consistency by falling back to default type
Although unrelated to this PR, the TODO regarding activity type model consistency has been resolved by always resetting to a default compatible type when the activity type is not consistent (not present or not compatible).
We also remove the invalid activity type from the activity values if present, to prevent the incompatible type from being restored.
Task-6255045The website configurator no longer uses a moving background that could slow down some devices. Keeping the background fixed helps the page feel more responsive and improves the setup experience for users.
Original PR description
Background animation in the configurator caused performance issues on some devices and could make the page feel laggy. This commit removes the animation and keeps the background fixed. task-6497101 <img width="1911" height="921" alt="image" src="https://github.com/user-attachments/assets/951bf4db-6c22-440d-8148-6626ebda3fdf" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Email notifications no longer send readers to internal contact records when they see a partner mention. Mentions are shown as non-clickable highlighted text, avoiding confusing or inaccessible links for email recipients.
Original PR description
**Before this PR:** Partner @mentions in email notifications linked to the corresponding partner record. **After this PR:** Partner @mentions now render as links when the mentioned partner has an email address. If the mentioned partner has no email address, the @mention is rendered as plain text instead. task-4844982 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Users can now find relevant ADEME emission factors more easily by filtering by location and seeing more recent factors first. The update also improves how dates, locations, units, and currencies from the ADEME database are interpreted, reducing irrelevant or confusing results.
Original PR description
Purpose: Today, it is complex for the user to find the relevant emission factors to use. For instance, when searching for "electricity", 406 records are found, many of which have the same name but…
Purpose: Today, it is complex for the user to find the relevant emission factors to use. For instance, when searching for "electricity", 406 records are found, many of which have the same name but different emission values. To improve the user experience, we should be able to filter by country and have the most recent factors shown first in the list view. In this commit, we add some flexibility on the validity dates given by the ADEME database. For instance, the following format dates are now parsed correctly: - 2026 - déc-18 - 31-mars-21 - Année 2008 Additionally, the location and sub-location are now taken into account (for the ADEME database) and stored in new fields (country_ids, state_ids). Some parsing and mapping were required to map those locations/sub-locations to existing records in the DB (a new CSV data file was added for this purpose). We also added a new filter to filter on factors that are relevant compared to the user's location (it compares the user's company's country to the ones of the factors). We also handle more units of measure and currencies, and we ignore some unknown units that are not relevant for the user. task-6109010
Financial reports now avoid unnecessary database work when preparing ledger queries. This reduces server resource usage significantly on large databases and should make affected reports load faster without changing report results.
Original PR description
Prior to this commit, the financial engine's query generation included redundant joins to `account_move` (INNER JOIN) and `res_partner` (LEFT JOIN). Neither table is utilized in the SELECT, WHERE,…
Prior to this commit, the financial engine's query generation included redundant joins to `account_move` (INNER JOIN) and `res_partner` (LEFT JOIN). Neither table is utilized in the SELECT, WHERE, GROUP BY, or ORDER BY clauses of these financial reports. These joins have been removed based on the following justifications: 1. account_move (INNER JOIN): Because `move_id` is a NOT NULL foreign key constraint on the line table, orphan lines cannot exist and the join acts as a no-op. Furthermore, the filter on entry state utilizes `parent_state` which is already denormalized on `account_move_line`. Removing this INNER JOIN allows the planner to avoid a massive, resource-heavy Nested Loop over the parent table's primary key index. 2. res_partner (LEFT JOIN): While PostgreSQL's optimizer was already utilizing "Left Join Elimination" to strip this out of the execution plan at runtime, removing it from the query builder cleans up the codebase and prevents unnecessary overhead in the query construction phase. Benchmarks on large database shows a large performance optimization: - Shared Hit Blocks: ~940,000 -> ~51,800 (a ~94.5% memory page reduction) Before Plan: https://explain.dalibo.com/plan/e3e2193968bf2a18 After Plan: https://explain.dalibo.com/plan/1dgdh22f68d89aca
Odoo can now receive payment status updates from the Odoo Fin proxy through a webhook. This helps keep online payment records and batch payments more current while avoiding duplicate refresh jobs.
Original PR description
This commit adds a webhook to allow Odoo Fin proxy to communicate with the Odoo database that a payment status has been updated. Once the call received, the code is making sure first that we have an associated client_id and at least a payment or a batchpayment with the payment identifier. This is also make sure that the cron is not already triggered to avoid multiple calls as the cron will fetch the status for all payments and batches. task-6377052
Leave types that deduct extra hours can now let employees take time off even when their extra-hours balance is not yet sufficient. This gives businesses more flexibility to manage time off policies while still tracking the resulting negative overtime balance.
Original PR description
When "Deduct Extra Hours" is checked on a leave type, add a new "Allow Negative?" checkbox that allows employees to take time off even if they don't have enough extra hours accumulated yet. task-5017245
Repeated copies of the same attachment, such as email signature images, are now grouped into one preview in the chatter attachment box. Users can expand the group to view, download, or remove individual copies, making important files easier to find while preserving access to every attachment.
Original PR description
Signature images ride along with every mail, so the same picture ends up attached to a record over and over. The attachment box lists every one of them, burying the files users actually came for.…
Signature images ride along with every mail, so the same picture ends up attached to a record over and over. The attachment box lists every one of them, burying the files users actually came for. This is a recurring complaint from the support team. Attachments holding the same content are now shown as a single preview carrying a counter on its bottom end corner. Clicking the counter unfolds the copies, each with its date, so that any of them can still be downloaded or removed on its own. Removing the preview itself removes the whole group, as that is what it stands for. Copies are matched on their checksum, and only grouped in the chatter attachment box: on a message the attachments are part of what the author wrote, so hiding some of them would drop information. task-6428149 https://github.com/odoo/enterprise/pull/126070 <img width="643" height="614" alt="image" src="https://github.com/user-attachments/assets/bb44d1bd-952e-409e-ae91-029ce88c87bb" /> --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Binary files can now carry their filename directly, making attachment names easier to preserve and reducing the need for separate filename fields. File previews and reads avoid sending unnecessary encoded content, which can improve performance and browser caching across affected apps.
Original PR description
Add `filename` to `BinaryValue`. We can now write a dict {file_name, content} on binary fields. For attachments, the file name is stored in ir.attachment.name.
We remove the need to have "bin_size" context value and don't transfer base64-encoded data for `web_read`.
odoo/enterprise#118187
odoo/documentation#18337
task-6303991
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prThe Point of Sale product configuration window now shows product reference codes again, helping staff identify the right item more easily. Searching by a variant reference now opens the matching product variant, reducing selection mistakes during checkout.
Original PR description
We reintroduce the default code on the product configuration modal, and ensure that searching for a variant reference opens the right variant. task-6463377 Forward-Port-Of: odoo/odoo#283846 Forward-Port-Of: odoo/odoo#282707
Belgian payroll reporting now supports the Employee Participation declaration alongside the existing 273S flow. This gives payroll teams a more complete 273.XX reporting process for meeting Belgian compliance requirements.
Original PR description
Task: 6361345
Duplicate attachments, such as repeated email signature images, are now grouped into one preview in the chatter attachment box. Users can expand the group to view, download, or remove individual copies, making important files easier to find while preserving access to every attachment.
Original PR description
Signature images ride along with every mail, so the same picture ends up attached to a record over and over. The attachment box lists every one of them, burying the files users actually came for. This is a recurring complaint from the support team. Attachments holding the same content are now shown as a single preview carrying a counter on its bottom end corner. Clicking the counter unfolds the copies, each with its date, so that any of them can still be downloaded or removed on its own. Removing the preview itself removes the whole group, as that is what it stands for. Copies are matched on their checksum, and only grouped in the chatter attachment box: on a message the attachments are part of what the author wrote, so hiding some of them would drop information. task-6428149
This update modernizes how Odoo handles binary file information, such as file names, checksums, and whether full file data is loaded. It also updates related settings and tests across several apps to keep file handling consistent and reduce unnecessary data loading.
Original PR description
odoo/odoo#266082
Belgian payroll payslips now include more detailed explanations for additional salary rules, making payroll calculations easier to understand. The underlying explanation logic was also simplified, improving maintainability without changing the payroll outcome.
Original PR description
- Add detailed explanations for additional salary rules on the payslip. - Refactor existing explanations to stop using `localdict` for passing values. Pass it directly via functions such as `result` and `rate` Task ID: 6450081
Draft payslips are now recomputed when they overlap with a salary adjustment. This helps payroll teams avoid outdated calculations and reduces the risk of incorrect payments before payslips are finalized.
Original PR description
…ustment task-6479469
Online stores can now set a minimum quantity that shoppers must buy for specific products. Product pages and carts automatically enforce the minimum, including when the same product appears in different units of measure, helping businesses protect pricing, packaging, or fulfillment requirements.
Original PR description
Add support for a minimum quantity on eCommerce products. The product page now initializes the quantity to the configured minimum and prevents decreasing below it. The cart also blocks quantity reductions that would violate the constraint. The minimum quantity is computed across all instances of the same product in the cart, including different UoMs converted to the product's base UoM. Changing the UoM automatically adjusts the quantity if needed. Removing one UoM while another remains in the cart increases the remaining quantity to preserve the constraint. Enterprise: https://github.com/odoo/enterprise/pull/122657 task-6354127
Manufacturing orders now handle expected work order durations more accurately for full production runs. The update also prevents production quantities from being changed too early and makes it easier to recover cancelled backorder steps, reducing disruption on the shop floor.
Original PR description
Some more improvements to refine the production process: - Allow computation of workorders' expected duration for a full production. - Remove writing into `qty_produced` while setting workorders states, unless its being marked as done. Task: 6421044 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278809
Rental products can now require a minimum total rental amount before customers can add them to the cart. This helps businesses enforce rental sales rules consistently by checking rental duration and quantity together, and by preventing cart changes that would fall below the required minimum.
Original PR description
Extend the minimum quantity feature to rental products. The constraint is based on `periodicity × quantity ≥ minimum quantity`. The product page disables Add to Cart until the constraint is satisfied, while taking existing cart lines into account. The cart prevents quantity reductions and date changes that would break the constraint. As for regular products, the minimum is evaluated across all cart lines and remaining quantities are automatically adjusted when needed after removing a line. Community: https://github.com/odoo/odoo/pull/273732 task-6354127
Frontdesk now checks that email, SMS, and WhatsApp notification templates are properly set before those alerts can be enabled. It also prevents templates in active use from being deleted, reducing missed visitor notifications and setup mistakes.
Original PR description
Improve the validation of Frontdesk host notification templates: - Ensure Email, SMS, and WhatsApp notification templates are configured whenever their corresponding notification is enabled. - Prevent deletion of notification templates that are currently used by Frontdesk stations. Fix: - Update the `mail_template_id` domain to use `frontdesk.visitor` instead of `frontdesk.frontdesk`, since the email template is related to the visitor model. TaskId-6416010
Belgian payroll now helps ensure eligible employees receive a prorated 13th month payment when they leave the company. A dedicated employee-page action appears only when the employee qualifies, reducing manual work and improving payroll accuracy around departures.
Original PR description
When a Belgian employee leaves the company (fired or resigned) and has worked long enough (6 months for fired employee and 3 years for resigned employee), they are owed a partial 13th month payment. This commit adds a "13th Month" button on the employee's page, which only shows up when the employee actually qualifies, and creates a payslip with the correct partial amount for the months they worked. Also fixes a case where that amount could come out wrong if the payslip was generated before the departure date was officially confirmed. task-6439087
Payroll run cards now adapt better across desktop, narrow layouts, and phones, keeping key actions easier to access and preventing crowded content from overflowing. Metrics and step actions have been simplified so users can scan payroll runs more clearly and act faster.
Original PR description
The pay run card laid its name, kpis, steps and action buttons out on a single row. Below the xl breakpoint the buttons collapsed into the overflow menu, and on narrower screens the kpis and the…
The pay run card laid its name, kpis, steps and action buttons out on a single row. Below the xl breakpoint the buttons collapsed into the overflow menu, and on narrower screens the kpis and the steps were squeezed until they spilled out of the card. Keep the action buttons rendered inline at every size: only the remaining actions, the deletion and the smart buttons stay in the ellipsis menu. Fold the kpis and the steps away once the card can no longer hold everything on one row. A chevron at the bottom of the card unfolds them into a row of their own, kpis on the left and steps on the right, and the fold is driven by a container query so a card narrowed by the open chatter behaves like a narrow screen. Only the standalone card above a payslip list folds; the pay runs kanban lists many cards at once and keeps them inline. On phones the kpis are dropped altogether, the steps stay on show, and the action buttons and the overflow menu dock to a bar at the bottom of the screen. Restyle the metrics: drop the icons, mute the labels and enlarge the amounts, keeping the currency symbol and the whole units at full size with the decimals small and muted. A field renders an amount as a single string, so a payrun_kpi widget splits it; the Belgian and Saudi metrics reuse the same markup and follow. Show only the step's own action inline. `is_priority` raises the inline budget from one button to two rather than marking a button prominent, and "Add Employees" was the only flagged button in the version, time, attendance and payslip steps, so it was buying the second slot that Continue and Validate sat in. Drop its flag and anchor the inherited buttons on it rather than on the deletion, leaving each step's own action first and "Add Employees" in the ellipsis menu. Keep the pay run name's underline hidden until the card is hovered, so the card reads as a title rather than as a form. task-6361830
Clicking a chatter notification now opens the related record form immediately instead of first opening a chat window. This reduces extra steps for users and helps them get to the relevant business information faster.
Original PR description
Before this commit: Clicking on a chatter notification in the systray would open the chat window, requiring users to click Open Form View to access the related record. After this commit: Clicking on a chatter notification now opens the corresponding form view directly, reducing the number of clicks and enhancing user efficiency. task-4681025 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Turkish payroll rules have been updated with the 2026 payroll parameters, including clearer naming for the minimum net wage and configurable SSI contribution settings. This helps payroll teams calculate employee contributions more accurately within the current legal framework.
Original PR description
- Update the Turkish payroll rule parameters for 2026. - Rename the minimum wage parameter to 'Turkiye Minimum Net Wage'. - Add configurable parameters for the SSI minimum contribution base and employee contribution rate. - Update the SSI contribution computation to account for both the minimum and maximum contribution bases. **task-6397284** Forward-Port-Of: odoo/enterprise#128658 Forward-Port-Of: odoo/enterprise#125985
Stock quantity updates now reuse the same warehouse lookup when processing multiple products. This reduces unnecessary database work during batch operations, helping inventory-related actions run more efficiently without changing user workflows.
Original PR description
When `_inverse_qty_available` processes multiple products, it performs the same warehouse search for every eligible product, resulting in redundant queries during batch operations. Look up the warehouse lazily once and reuse it for all products in the recordset. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283564
This update refines several VoIP screens and messages to make call-related workflows clearer for users. It replaces a log wizard label with an icon, renames the main outgoing number setting to a more understandable term, and improves the wording of tracking emails.
Original PR description
see commit titles task-6487015
This change improves Odoo's internal testing tools so simulated dates and times can be advanced during automated checks. It helps teams validate future marketing automation work more reliably, including incremental synchronization and application overhaul efforts.
Original PR description
Allows notably to make time move forward (tick). Prepares Task-6425785 [marketing_automation] Incremental sync Prepares Task-3866422 [marketing_automation] Overhaul application
This update improves internal testing for Marketing Automation scheduled jobs, helping ensure campaign activities run reliably over time. It also prevents test scenarios from getting stuck when scheduled jobs trigger repeatedly, reducing risk in future application improvements.
Original PR description
Forward-Port-Of: odoo/enterprise#128884 Forward-Port-Of: odoo/enterprise#128522
Loading indicators now appear without shifting button content or making the page feel jumpy. This improves visual stability and polish when users click actions that need time to complete.
Original PR description
The helper function `addLoadingEffect` disables the button and adds an inline font-awesome icon as a spinner. This can cause elements to shift on the page. Additionnally, the font-awesome icon has a…
The helper function `addLoadingEffect` disables the button and adds an inline font-awesome icon as a spinner. This can cause elements to shift on the page. Additionnally, the font-awesome icon has a very light imbalance that makes it wiggle instead of staying centered. Instead, we want to leave the layout as unaltered as possible while keeping the loading behavior. | Snippet | Before | After | | --- | --- | --- | | Button | <img width="174" height="74" alt="image" src="https://github.com/user-attachments/assets/b88dd91c-4d49-485e-8d10-b1a9afe37901" /> | <img width="168" height="131" alt="image" src="https://github.com/user-attachments/assets/88261d9b-19d2-42bf-8a2f-ea57c55954db" /> | | Accordion | <img width="633" height="89" alt="image" src="https://github.com/user-attachments/assets/9eeaf7d4-1933-4322-9e70-1d3c93ffa7d3" /> | <img width="650" height="134" alt="image" src="https://github.com/user-attachments/assets/2ee590cb-7b63-4d6c-bbae-472616530921" /> | | Carousel indicator | <img width="228" height="87" alt="image" src="https://github.com/user-attachments/assets/39fd0685-0517-456a-a1fd-6914f9ee4dbc" /> | <img width="194" height="99" alt="image" src="https://github.com/user-attachments/assets/2eaf1da3-d6eb-4ce3-8088-188c03508e92" /> | task-5221179
India withholding reports now use the shared withholding framework instead of older country-specific rules. This keeps reporting aligned with the latest accounting logic and reduces inconsistencies after the India-specific implementation was removed.
Original PR description
Update report domains to align with the generic withholding framework after removing the India-specific withholding implementation. com:https://github.com/odoo/odoo/pull/273075 upg:https://github.com/odoo/upgrade/pull/10681 task-6324221
The spreadsheet component has been updated to a newer version, bringing general improvements to the spreadsheet experience in Odoo. This helps keep spreadsheet features current and supports better reliability for users working with spreadsheet-based data.
Original PR description
Task: [6219600](https://www.odoo.com/odoo/project/2328/tasks/6219600) --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
India accounting now uses Odoo’s shared withholding tax framework instead of a country-specific setup. This simplifies future maintenance, aligns terminology with common Indian TDS usage, and prepares automatic withholding tax application on vendor bills in a future update.
Original PR description
Previously, India used a custom withholding implementation. The generic `l10n_account_withholding_tax` module now supports the required Indian withholding features, making the custom implementation unnecessary. With this commit, `l10n_in` adopts the generic withholding framework and removes the India-specific withholding implementation, including section alerts and related warnings. Additionally, the `l10n_in_tax_type` selection values `tds_purchase` and `tds_sale` are merged into `tds`. The purchase/sale distinction is now handled by the `type_tax_use` field. In future, withholding taxes will be added to the chart of accounts and automatically applied to vendor bills according to the applicable rules. ent:https://github.com/odoo/enterprise/pull/122266 upg:https://github.com/odoo/upgrade/pull/10681 task-6324221
The blog module gets a refreshed design with new page layouts, modern navigation, updated demo content, and more customization options for blog lists and individual posts. This helps businesses present content more professionally and gives website editors better control over how articles are showcased.
Original PR description
- requires : - https://github.com/odoo/upgrade/pull/7957 - https://github.com/odoo/documentation/pull/16596 ------------ ## Blog redesign This PR introduces a redesign of the blog module, featuring…
- requires :
- https://github.com/odoo/upgrade/pull/7957
- https://github.com/odoo/documentation/pull/16596
------------
## Blog redesign
This PR introduces a redesign of the blog module, featuring **new layouts**, an **updated set of demo data** as well as **new features**.
### Layout
This PR introduces **five** new layouts in addition to the existing ones :
#### Grid layouts
<details>
<summary>Grid</summary>
<img width="1322" height="864" alt="image" src="https://github.com/user-attachments/assets/4482cab2-a72f-49a2-ba07-ba7343c78e47" />
</details>
<details>
<summary>Split</summary>
<img width="1724" height="920" alt="image" src="https://github.com/user-attachments/assets/dee9fbbf-09be-4f0e-b50e-768dc3d97271" />
</details>
#### List layouts
<details>
<summary>Minimal</summary>
<img width="1331" height="504" alt="image" src="https://github.com/user-attachments/assets/f027ce7b-f52b-4d4c-806b-09be1f5ebf46" />
</details>
<details>
<summary>Compact</summary>
<img width="1343" height="777" alt="image" src="https://github.com/user-attachments/assets/52ed31c8-e9eb-40b6-8d27-242c17e84d81" />
</details>
<details>
<summary>Regular</summary>
<img width="1351" height="860" alt="image" src="https://github.com/user-attachments/assets/8218cf13-3868-4b4b-9838-aff322cc04b3" />
</details>
<details>
<summary>Large</summary>
<img width="1341" height="860" alt="image" src="https://github.com/user-attachments/assets/31d461b5-9a50-4cc7-8f71-88342f02aa5b" />
</details>
### Features
- $\color{Red}{\textbf{(NEW!)}}$
- Introduce a **Promote last** option for the default grid layout, which puts the emphasis on the most recent article;
- Allow to set the page width to **Large**
- Added a new option to achieve a full-width cover on the blog post page.
### Demo data
All the demo data have been totally reviewed to showcase the new design
### Various improvements
- Refine the options available by organising them into sections;
- Revamp the relations between options, dissociate options that were not related and nest the ones which are;
- Refine sidebar and behaviour
- Dissociate author & date in two different option + allow to choose the formatting of the date between different formats
task-3083656
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-prFixes issues in Odoo's JSON logging so ignored fields and test-related log information are handled correctly. Adds automated checks to help prevent these logging problems from returning, improving reliability for monitoring and troubleshooting.
Original PR description
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also…
The JsonFormatter has two bugs - the ignore list is not working as expected - in 18.0-18.4 the 'test' key is broken This commit add tests to ensure those behavior works as expected While on it, also adds a `additional_record_keys` parameter to allow to specifically add keys to the default list, without having to override the whole list, and add additional default keys (exc_info and test) The previous `ignored_record_keys` default value was possible to remove by calling `JSONFormatter(ignore_record_keys=[])` The purpose was to be able to easily include all keys and ignore the default ingnore list, but this makes the additional blacklisting of a few keys more tedious, and the general usage and implementation more complex `JSONFormatter(ignore_record_keys=[*JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS, 'other key'])` To simplify the logic, **this is not the case anymore**, so to include all keys something like this would be needed `JSONFormatter(additional_record_keys=JSONFormatter.DEFAULT_IGNORED_RECORD_KEYS)` Or an hardcoded list. Forward-Port-Of: odoo/odoo#284051 Forward-Port-Of: odoo/odoo#279049
This fix prevents the timesheet assistant from accidentally changing event data and resolves errors that could appear when removing or viewing certain timesheets. Users should experience fewer interruptions and more dependable timesheet handling.
Original PR description
## [FIX] timesheet_grid: avoid altering consumedEvents Before this commit, the objects inside consumedEvents attribute are altered because we keep the reference of those objects. This commit avoid altering the consumed events. ## [FIX] timesheet_grid: use recordsByStart instead of records Forward-Port-Of: odoo/enterprise#128036 Forward-Port-Of: odoo/enterprise#127698
This fix prevents planning shifts from failing when no related sales order line is attached. It ensures the customer field is still set safely, improving reliability for sales planning workflows.
Original PR description
Before this commit, when the shift has no SOL set, the `_compute_partner_id` crashes because the value for partner_id field is not set for that shift. This commit fixes the compute method of partner_id to make sure the value is correctly set for all shifts. Forward-Port-Of: odoo/enterprise#128965
This fixes an internal test for appointment rescheduling so it behaves consistently when demo data is present. It helps prevent false test failures without changing the customer-facing appointment experience.
Original PR description
In test_reschedule_appointment_event the tracking is rendered by the public user, which has no timezone hence fallback to UTC. But the expected values are formatted by the test environment, running as OdooBot, whose timezone demo data sets to Europe/Brussels. Without demo data both fall back to UTC and the test passes. Format the expected values in UTC as well. Runbot-946307
Timesheet suggestions now handle away-from-keyboard periods more reliably, so breaks and inactive time are less likely to be missed or overwritten. This helps employees and managers get a more accurate view of working time when using ActivityWatch-based timesheet assistance.
Original PR description
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was…
## Previous Behavior Before this Commit 1. When key and non‑key events were merged to build the final suggestion timeline, key events always took priority over AFK events, even when the key event was not “always active.” This caused AFK events to be incorrectly overridden. 2. During event normalization, certain events were lost entirely, resulting in important events not being counted. 3. When merging two event timelines, zero‑duration gaps were treated as valid, preventing proper merging of surrounding events. 4. ActivityWatch sometimes produced empty gaps instead of AFK events, causing breaks to go unrecorded. ## New Expected Behavior After this Commit 1. Events now follow the updated priority system: a. Always‑active key events b. Always‑active non‑key events c. Non‑key AFK events d. Other key events e. Other non‑key events 2. Events are now shortened or split so that the latest event always has priority, while minimizing unnecessary event removal. 3. Zero‑duration gaps are skipped when merging event lists. 4. Any gap larger than 3 minutes, between the first and last event and containing no events is automatically filled with an AFK event. ## Additional Notes Because point 4 introduces additional AFK events, several tests were updated to reflect the new behavior. task-[6455412](https://www.odoo.com/odoo/project/4105/tasks/6455412) Forward-Port-Of: odoo/enterprise#128039 Forward-Port-Of: odoo/enterprise#127811
Inventory move lines now keep the transfer's original scheduled date after validation instead of switching to the processing date. This makes Moves History filtering, grouping, and sorting by Scheduled Date match the date shown on the transfer, improving reporting accuracy.
Original PR description
### Problem `stock.move.line.scheduled_date` is related to `move_id.date`, and `stock.move.date` only holds the scheduled date **until the move is done** — at validation it is overwritten with the…
### Problem `stock.move.line.scheduled_date` is related to `move_id.date`, and `stock.move.date` only holds the scheduled date **until the move is done** — at validation it is overwritten with the processing date, as its own help states. So on a done move line the field returns the effective date under a "Scheduled Date" label. It shows up in Moves History (Inventory > Reporting), which lists done lines by default: filtering, grouping or sorting by "Scheduled Date" silently uses the effective date, and it contradicts the "Scheduled Date" displayed on the transfer, which does survive the validation (`stock.picking._compute_scheduled_date` ignores done moves). **Steps to reproduce** 1. Create a receipt scheduled tomorrow and validate it today. 2. Inventory > Reporting > Moves History, group by "Scheduled Date". 3. The line falls under today instead of tomorrow, while the transfer form still shows tomorrow. ### Fix Follow `picking_id.scheduled_date`, which keeps the scheduled date once the transfer is done. The field is only displayed in `stock.view_move_line_tree_detailed`, and every action using that view (`stock.action_get_picking_type_operations`, the Prepare Wave actions and the Add to Wave wizard) already restricts the lines to those belonging to a transfer, so no view loses a value it used to show. I hereby agree to the terms of the CLA available at: https://www.odoo.com/cla
Users who manually replenish stock will now see the expected notification when a purchase order is created. This makes the replenishment process clearer and helps teams confirm that their order action was successful without having to search for the purchase order manually.
Original PR description
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track…
Currently when the user does manual replenishment no notification is displayed. ## Steps to produce: - Install Inventory and Purchase - Create a product `Chocolate Icecream` and Enable `Track Inventory` - Purchase > Add a Vendor `Ice cream man` - Reordering rules > Create a new reordering rule and save: - Trigger: Manual - Min: 5 - Max:10 - Press the `Order` button ## Observed Behavior: No notification is displayed about the newly created purchase order. ## Root cause: When the Order button is pressed, the `action_replenish` method is called. This method invokes `_procure_orderpoint_confirm` at [1]. The `_procure_orderpoint_confirm` function is responsible for creating procurements from orderpoints. During this process, it retrieves the procurement values using `_prepare_procurement_values` that are later used at [2]. However, `_prepare_procurement_values` only includes the orderpoint in the procurement values when the orderpoint's trigger is set to automatic, and not when it is manual, as shown at [3]. These procurement values are then used by `_run_buy` to create a purchase order and purchase order line at [4]. Since the orderpoint is not linked to the purchase order line in this case, no matching order is found at [5], which leads to the reported issue. **Which commit caused this unintentional behavior?** This behavior was unintentionally introduced by this [commit](https://github.com/odoo/odoo/commit/2a0d2c64d0027f540101447289b4c1a10cb3ecdf) . That commit fixed an issue where purchase order lines were not being merged for temporary manual orderpoints that are created dynamically based on product demand. [1]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L342-L349 [2]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L737-L741 [3]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L687-L701 [4]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock_rule.py#L156-L165 [5]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/purchase_stock/models/stock.py#L276-L296 [6]- https://github.com/odoo/odoo/blob/c076281dedeed2e25844c43c49ec17511434e3fc/addons/stock/models/stock_orderpoint.py#L365 [7]- https://github.com/odoo/odoo/blob/6a84d3e519892be333552e2e0ebf8da87e0a760c/addons/purchase_stock/models/purchase_order_line.py#L380-L384 ## Solution: Instead of removing the orderpoint ID from the procurement values, we reuse the same conditions used to identify temporary orderpoints for cleanup at [6]. Based on this, we determine how purchase order lines should be merged in the `_run_buy` method. With the previous implementation, no orderpoint was included in the procurement values. As a result, the condition at [7] checking for orderpoints always evaluated to True, causing the system to identify an existing purchase order line for the same product as a merge candidate. This solution allows us to retain that fix as well as avoid the error of notifications not showing up. opw-6311520 Forward-Port-Of: odoo/odoo#283853 Forward-Port-Of: odoo/odoo#271993
Argentine delivery operations using class X document types can now be saved without entering CAI authorization details or an expiration date. This aligns the workflow with local regulations, where those fields are only required for class R delivery notes.
Original PR description
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to…
Currently, when the user attempts to create a delivery operation for a class X document type, the system prompts the user to provide values for the CAI and CAI Expiration Date fields. ## Steps to produce: - Install `l10n_ar_stock` with demo data - Switch Company to `(AR) Exento` - Create a warehouse - Configuration > Operation Types > Delivery Orders - Set Document Type to `'(94) MAILING X' `and try to save ## Observed Behavior: The fields 'CAI' and 'CAI Expiration Date', which represent the authorization code and expiration date issued by the government, are currently configured as required fields. **Expected Behavior:** As specified on the [government site](https://www.argentina.gob.ar/normativa/nacional/resoluci%C3%B3n-1415-2003-81316/actualizacion#:~:text=Los%20datos%20indicados%20en%20el%20inciso%20a%29%2C%20puntos%207%2C%2010%2C%2011%2C%2012%20y%2013%2C%20s%C3%B3lo%20ser%C3%A1n%20para%20los%20remitos%20clase%20%27R%27%2E): > > 12. Printing authorization code, preceded by the acronym 'CAI No. ...'. > 13. Expiration date of the receipt, preceded by the legend 'Expiration Date ...' > > 'The data indicated in section a), points 7, 10, 11, 12 and 13, will only be for 'R' class delivery notes.' These statements indicate that the information mentioned in points 12 and 13, including the **CAI** and **CAI Expiration Date** fields, is applicable only to **'R'** class delivery notes. Therefore, for class X delivery notes, these fields should be optional rather than required. ## Root Cause: According to [1], the field is configured as a required field when a Document Type ID is selected. This configuration causes the **CAI** and **CAI Expiration Date** fields to become mandatory, regardless of the document type requirements defined by the government specification. [1]- https://github.com/odoo/odoo/blob/62b05c4ea61942072b6b1fb420fe3efedb11ed14/addons/l10n_ar_stock/views/stock_picking_type_views.xml#L11-L16 ## Solution: Apply constraints that align with the government specifications, allowing the CAI and CAI Expiration Date fields to remain optional for document types where they are not required. opw-6359503 Forward-Port-Of: odoo/odoo#283822 Forward-Port-Of: odoo/odoo#275533
Incoming Peppol vendor bills are now checked against previously imported bills before they are processed. This prevents duplicate bills from being created and marks repeated messages as handled so they do not reappear later.
Original PR description
Many users were receiving duplicate vendor bills. The issue was that duplicates were never detected in the receiving flow. Every incoming message returned by the proxy was processed and turned into a new `account.move`, even if it had already been imported previously. This commit filters out messages whose UUID already matches an existing `account.move` before processing them, and acknowledges those duplicates on the IAP side so they are not received again on the next run. task-5930116 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282349 Forward-Port-Of: odoo/odoo#274963
Fixes an error that occurred when users clicked the Recorded button on field service interventions. Users can now reliably view the timesheets logged for an intervention without needing an extra project planning integration installed.
Original PR description
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field…
**Problem:** Clicking the "Recorded" smart button on a field service intervention raises an AttributeError instead of listing the timesheets logged on it. **Steps to reproduce:** 1. Install the field service billing feature (Planning > Configuration > Settings > Field Service > "Invoice your time and materials to your customers") without installing Project's planning integration 2. Set the project in Planning > Configuration > Settings > Field Service 3. Create an intervention and assign a resource to it 4. Click the "Recorded" smart button **Current behavior:** 'super' object has no attribute 'action_open_timesheets' **Expected behavior:** The timesheets logged on the intervention are listed. **Cause of the issue:** `action_open_timesheets` on `planning.slot` is defined in two modules only: `project_timesheet_forecast` provides the base implementation, and `planning_field_service_sale_timesheet` extends it through `super()`. Since `59a04091c403` dropped `project_timesheet_forecast_sale` from the dependencies of `planning_field_service_sale_timesheet`, nothing guarantees the base implementation is part of the model's inheritance chain anymore: `project_timesheet_forecast` is auto installed only together with `project_forecast`, which no module of the field service stack depends on. The smart button is rendered by `planning_field_service_sale_timesheet` itself, so it stays visible in such an installation while the `super()` call has nothing to resolve to. **Fix:** That same commit already made the field service module self-sufficient for `_get_timesheetable_project`, `_compute_allow_timesheets` and `_compute_allow_billable`, leaving the project forecast flavour to the `project_timesheet_forecast_field_service_sale` bridge, and `action_open_timesheets` is the only method that was left relying on the other stack. Building the action from the module's own hooks preserves that separation, whereas depending on `project_timesheet_forecast` again would pull Project back into every field service installation, which is precisely what that commit set out to avoid. opw-6391972 Forward-Port-Of: odoo/enterprise#126489
The Belgian salary configurator now calculates wages consistently when employees have extra-legal leave and a mobility budget. This prevents the mobility budget from being incorrectly adjusted for leave, so employer cost and gross wage figures align with the standard payroll formula.
Original PR description
Forward-Port-Of: odoo/enterprise#112723
Adds automated coverage to ensure currency translation adjustments use the correct exchange rates when the company currency changes over time. This helps prevent inaccurate financial report values in fluctuating-rate scenarios.
Original PR description
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD…
Following the fix made in community branch, this adds a test veryfing the expected behavior in case of a fluctuating rate for the domestic currency. Scenario 2: fluctuating domestic (USD) rate USD rate=1 from Jan 1 to Jun 30, USD rate=3 from Jul 1 to Dec 31 EUR rates unchanged: 2 from Jan 1, 4 from Jul 1 Correct conversion factors (= USD_rate / EUR_rate): Jan 1 – Jun 30 (182 days): 1/2 = 0.50 Jul 1 – Dec 31 (184 days): 3/4 = 0.75 Current rate at 2020-12-31: 3/4 = 0.75 Correct average rate: (0.50 * 182 + 0.75 * 184) / 366 = 229/366 ≈ 0.62568 Previsouly bugged average rate (USD fixed at current=3): (1.50 * 182 + 0.75 * 184) / 366 = 411/366 ≈ 1.12295 Historical equity rates (correct vs previously bugged): Mar 1 (USD=1, EUR=2): correct = 1/2 = 0.50; buggy = 3/2 = 1.50 → 40 * 0.50 = 20 vs 40 * 1.50 = 60 Oct 1 (USD=3, EUR=4): correct = 3/4 = 0.75; buggy = 3/4 = 0.75 → 60 * 0.75 = 45 (same by coincidence) task-5953104 Forward-Port-Of: odoo/enterprise#125363 Forward-Port-Of: odoo/enterprise#123055
Odoo now correctly detects when an internal stock transfer leaves a replenished source location short of stock. This ensures the Replenishment report creates the needed reordering suggestion, helping businesses avoid missed restocking actions after moving inventory between internal locations.
Original PR description
Steps to reproduce: ------------------- 1. Install `stock` module. 1. Enable the "Storage Locations" from setting. 2. Create an internal location and enable `replenish_location` on it and set…
Steps to reproduce:
-------------------
1. Install `stock` module.
1. Enable the "Storage Locations" from setting.
2. Create an internal location and enable `replenish_location` on it and set warehouse(WH) as Parent.
3. Create a storable product track by quantity with no on-hand quantity.
4. Create an internal transfer from the warehouse stock location to the new internal location.
5. Confirm the transfer.
6. Open the Replenishment report.
Issue:
------
No manual reordering rule is created for the product at the source location, although
the confirmed transfer makes its forecasted quantity negative.
If `replenish_location` is disabled on the destination, the expected reordering rule is created.
Cause:
------
When both the source and destination have `replenish_location=True`, Odoo considers both locations
inside the same replenishment area. Therefore, the internal transfer is not counted as either
incoming or outgoing, and no replenishment is created for the source location.
Code Flow:
Opening the Replenishment report calls
`stock.warehouse.orderpoint.action_open_orderpoints()`, which delegates the report preparation to `_get_orderpoint_action()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L324-L326
`_get_orderpoint_action()` first obtains every location that must be monitored for replenishment through `_get_orderpoint_locations()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L520
`_get_orderpoint_locations()` returns all locations whose `replenish_location` field is enabled:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L799-L800
All these locations are passed together to
`product.product._get_domain_locations_new()`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/product.py#L396-L464
This method treats the provided locations and their descendants as a set. Its move domains are equivalent to:
- incoming: destination is inside the set and source is outside;
- outgoing: source is inside the set and destination is outside.
Consider the following sibling locations:
WH
├── Stock
└── Replenish Location
and the transfer:
Stock -- 3 units --> Replenish Location
When `replenish_location` is disabled on the destination, the considered location set contains only `Stock`:
considered location set = {Stock}
The source is inside the set and the destination is outside:
source inside = True
destination outside = True
The transfer therefore matches the outgoing domain:
source inside AND destination outside
True AND True
= True
It is included in `moves_out`, and the preliminary forecast for `Stock` becomes:
0 on hand + 0 incoming - 3 outgoing = -3
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L552
The negative quantity is detected and a manual orderpoint is created.
When `replenish_location` is enabled on the destination, both sibling locations belong to the considered location set:
considered location set = {Stock, Replenish Location}
Both ends of the transfer are now inside:
source inside = True
destination inside = True
destination outside = False
source outside = False
The transfer matches neither aggregate domain:
incoming:
destination inside AND source outside
True AND False
= False
outgoing:
source inside AND destination outside
True AND False
= False
The transfer is considered internal to the considered location set and is therefore absent from both `moves_in` and `moves_out`:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L530-L540
This aggregate treatment conflicts with the next step, where `_get_orderpoint_action()` computes the quantity separately for each replenishment location:
https://github.com/odoo/odoo/blob/12a66c6931d81e1cce18f676836aca0b32090d16/addons/stock/models/stock_orderpoint.py#L549-L552
When `Stock` is evaluated separately, the internal transfer has already been discarded. Its calculated outgoing quantity is consequently zero:
0 on hand + 0 incoming - 0 outgoing = 0
As the quantity is not negative, the product is not scheduled for the final `virtual_available` computation and no manual orderpoint is created.
Fix:
----
Also retrieve moves whose source and destination are both inside the aggregate replenishment-location set.
Include these internal moves in both the incoming and outgoing grouped queries. The existing per-location path filtering then assigns each side correctly:
- the source replenishment location counts the move as outgoing;
- the destination replenishment location counts it as incoming.
For the reported transfer, this produces:
Stock:
0 on hand + 0 incoming - 3 outgoing = -3
Replenish Location:
0 on hand + 3 incoming - 0 outgoing = 3
This is correct because the report creates replenishment propositions per location, even though the initial move query is performed for all replenishment locations together.
---
opw-6462608
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#282168Sales order sections and subsections no longer show quantity delivered, delivery percentage, or unit price fields that do not apply to them. This keeps order lines easier to read and avoids confusion when reviewing structured sales orders.
Original PR description
On the SO form view, some fields that are not meant to be displayed on sections/subsections are displayed on them. These fields are: qty_delivered, qty_delivered_percent, and price_unit. Follow-up task: 6075605 and 6450100 <img width="1223" height="286" alt="screen" src="https://github.com/user-attachments/assets/f07e2343-c3ba-46b7-b6d3-b4e4d20491a2" />
This fixes a timing issue in the website page creation flow where the interface could remain blocked while redirecting to a newly created page. It makes the automated flow wait until navigation is fully complete, improving reliability of website testing and reducing false failures.
Original PR description
runbot-944311 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#278652
Belgian payroll demo records now use the correct meal voucher values and Belgian office work locations, making test employee data more accurate. The update also fixes a company mismatch on a demo vehicle to avoid multi-company errors during testing.
Original PR description
In Belgian demo data, several employees have an incorrect meal voucher employee share set to 0.00€ instead of the standard rate. Additionally, the default work address for BE test employees is set to a US location. This updates the demo records: - Sets meal voucher amount to 8.00€ and employee's share to 1.09€ (except for employees in JC 999). - Updates all BE test employees' work location to "Belgian offices". Task-6471822
The accounting app now correctly blocks fiscal year periods that fully contain an existing fiscal year. This helps prevent duplicate or conflicting accounting periods, reducing the risk of reporting and closing errors.
Original PR description
Before this commit: - The current constraint for overlap check allows if we define a new, larger fiscal year that completely swallows an existing smaller one (e.g., creating Aug 2025 - Nov 2026 when Sept 2025 - Oct 2026 already exists). After this commit: - The constrain domain was changed to consider the above missed case.
The tax totals display no longer shows cash rounding controls in sales and purchase documents, where they are not intended to be used. This keeps rounding behavior limited to accounting and invoicing, reducing confusion for users preparing quotes, orders, or purchase documents.
Original PR description
The cash rounding on the tax totals widget is intended to work only with accounting/invoicing, but not sales/purchases.
Customers can now redeem more than one eligible reward from the same loyalty coupon when they have enough points. This removes an incorrect block that prevented combining rewards such as a discount and a free product, improving checkout flexibility and loyalty campaign value.
Original PR description
Steps to produce: --- - Install the `website_sale_loyalty` module. - Navigate to Discount & Loyalty and create a new coupon program. - Keep the existing `10% Discount reward` and add a second reward…
Steps to produce: --- - Install the `website_sale_loyalty` module. - Navigate to Discount & Loyalty and create a new coupon program. - Keep the existing `10% Discount reward` and add a second reward of type `Free Product`. Select a product for the free product reward. - Generate a coupon and set its balance to `2` coupon points. - Open the website and add a product to the shopping cart. - Apply the generated coupon code. - Attempt to redeem both rewards (the 10% discount and the free product reward) using the same coupon. Issue: --- - When trying to apply the second reward, it shows `This program is already applied to this order.` Root cause: --- - Once a program was applied to the order, subsequent rewards from the same program were blocked, regardless of whether the customer had enough points to claim them. Solution: --- - If a reward from an already-applied program is still claimable (i.e, the customer has sufficient points), allow it to be applied to the order. opw-6247206 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Employees on flexible schedules without a set average daily hour value will now have full-day leave recorded correctly. This prevents leave requests from being saved as zero-duration, improving accuracy in absence tracking and payroll-related records.
Original PR description
…duration leave When a flexible schedule has no average_hour_per_day set (hours_per_day=0), _get_hours_for_date computed [12-0, 12, 12+0] = (12.0, 12.0), producing a zero-duration leave (date_from == date_to). Treat hours_per_day=0 like a fully flexible employee and return (0, 24) so the leave spans the full day. Task-6488608
Belgian payroll now correctly recognizes a full working day when an employee follows a schedule where some days have fewer contracted hours than others. This prevents payslips from incorrectly showing full days as half-day attendances, improving payroll accuracy for affected work schedules.
Original PR description
Bug: - Create a working sched were one day has less working hours than the rest. - when generating a payslip for an employee linked to that working sched , you'll have half-day attendances even…
Bug: - Create a working sched were one day has less working hours than the rest. - when generating a payslip for an employee linked to that working sched , you'll have half-day attendances even though he worked all his days Reason : - in _get_work_hours_split_half , when building work_data, we compare the duration worked by the employee that day not against the contractual amount of that that but instead we use self.resource_calendar_id.hours_per_day or the max hours per day on that working day , so the day with the least contractual hours on that working sched for exemple will fail this condition " float_compare(duration_sum, number_of_hours_full_day, 2) != -1" even if the employee worked that whole day. Fix: - for fixed scheds : we builed hours_per_dayofweek where we store the hours for each day of the week , later on , we check the weekday and retreive the corresponding official working hours on that day. - for variable scheds: because in this case each day can have its own officil working hours , we fetch the official hours of a certain date right before the logic that determines if it's a full or half a day. task - 6377396 Forward-Port-Of: odoo/enterprise#124100
This fixes an issue where AI assistants could attach request details to the wrong part of a resumed conversation. It prevents confusing or blank replies in Discuss and helps both Google Gemini and OpenAI produce responses based on the right user message.
Original PR description
`_append_context_part` puts the context of the current request on the last entry of the history, whatever that entry happens to be. That is the user's message on a normal turn, but a turn resumed from a `user_input_request` carries the answer back as a tool response, so the context landed on that instead: Google then received a turn mixing a `functionResponse` with a text part, which Gemini answers with a lone newline, posted as the agent's reply and shown in Discuss as a removed message. OpenAI appended it to the output of the tool call instead, making the model read the current context as part of what the tool returned. Both providers now walk back to the last message of the user and attach the context there, leaving tool responses untouched. A normal turn is unchanged, that message being the last entry already.
Shopfloor users can now finish the final work order in continuous production after entering produced quantities. The update also corrects displayed produced quantities when assigning serial numbers, reducing confusion and preventing blocked manufacturing steps.
Original PR description
Previously there was a limitation for continuous production in shopfloor, that blocked the user from marking a workorder as done after registering a quantity. This commit fixes it by assigning the production's `quantity_producing` to the work order's `qty_produced` if it is the final work order. This unblocks the user and allows them to complete the work order. Forward-Port-Of: odoo/enterprise#125787
Manufacturing change orders can now be created successfully from incoming emails sent to configured ECO aliases, even when no product is included in the email. This prevents bounced messages and ensures teams can capture change requests through email as intended.
Original PR description
Steps to reproduce --- 1. In Settings > Technical > Email > Alias Domains, create an alias domain (e.g. `example.com`). 2. Open the ECO Types configuration, pick a type (e.g. "BOM Updates"), and set…
Steps to reproduce --- 1. In Settings > Technical > Email > Alias Domains, create an alias domain (e.g. `example.com`). 2. Open the ECO Types configuration, pick a type (e.g. "BOM Updates"), and set its Email Alias to `bom-updates`. 3. Send an email to `bom-updates@example.com` with any subject and body. 4. The gateway fails to open the change order: the sender receives a bounce and no `mrp.eco` appears under that ECO type. Issue --- `product_tmpl_id` on `mrp.eco` is defined with `required=True`: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L261-L266 That constraint was added by ac635694 ([IMP] mrp_plm: ux improvements), which tightened the form UX but did not account for the mail gateway, which opens change orders without a product. A change order can be created from an incoming email: the alias declared on `mrp.eco.type` routes the message to `mrp.eco`, and `_alias_get_creation_values` injects only `type_id` into the creation values: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L55-L61 The gateway then builds the record with `message_new`, called from `_message_route_process`: https://github.com/odoo/odoo/blob/c6ef99510adcb079f34657aa66dcf191928e3355/addons/mail/models/mail_thread.py#L1553-L1575 https://github.com/odoo/odoo/blob/c6ef99510adcb079f34657aa66dcf191928e3355/addons/mail/models/mail_thread.py#L1402-L1413 An email carries no product, so those creation values have no `product_tmpl_id`. `required=True` is enforced only by the database `NOT NULL` constraint, so on any database where that constraint is present the gateway `create` raises and the incoming request is lost. A product is not actually needed until the change order starts its revision, where `product_tmpl_id` is first read to copy the BoM and gather its documents: https://github.com/odoo/enterprise/blob/79f9ff2ccea3153c457e286bbbca27794ccfdb57/mrp_plm/models/mrp_eco.py#L755-L777 opw-6351438
This fix makes forms with many product lines load and respond much faster by reducing unnecessary page layout recalculations. Large sales orders that previously took many seconds to display should now become usable much more quickly, improving productivity for users handling complex orders.
Original PR description
this is more like an experiment, to see if batching read and dom updates would help. this commit changes loading a SO view from 19.8s to 2.6s, so it looks like it helps 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#282788
This fixes how Indian localization classifies purchase entries for imported goods and services, especially credit and debit notes. It helps keep GST reporting aligned with the correct treatment for reverse charge services and moves invalid import-without-RCM cases out of scope.
Original PR description
Previously:
1.`purchase_cdnur_regular` section was assigned to credit/debit notes of:
- import of goods
- import of services without RCM However:
- import of goods should be handled through bill of supply
- import of services without RCM is not possible Therefore, with this commit, such journal items are moved to `purchase_out_of_scope`.
2.`purchase_imp_services` section included import of services both with and
without RCM. Since import of services without RCM is not possible, those
journal items are now moved to `purchase_out_of_scope`.
3.Credit/debit notes of import of services with RCM were previously moved to
`purchase_out_of_scope`, which was incorrect. With this commit, they are now
correctly moved to `purchase_imp_services`.
task-6330737
Forward-Port-Of: odoo/odoo#276721
Forward-Port-Of: odoo/odoo#272453Odoo now ignores a saved default search filter when its linked record no longer exists. This prevents affected screens from crashing and lets users continue working normally.
Original PR description
…'t exist Have a search view with a m2o field Have an action that sets search_default_m2o: [/BAD ID/] Before this commit there was a crash After this commit, we simply ignore the filter. task-6469841 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#282738
This fixes an issue where pressing Shift+Enter in Safari created a new paragraph instead of a soft line break in the editor. Users editing Knowledge articles on Mac Safari can now format text consistently with other browsers.
Original PR description
**Steps to reproduce:** - Use a Mac with Safari - Install Knowledge app - Go to any article - Press Shift+Enter to try to enter a soft line break - Hard split is done instead **Issue:** Shift+Enter causes a `insertParagraph` event instead of `insertLineBreak` in Safari, which triggers the `SplitPlugin` instead of the `LineBreakPlugin`. **Fix:** Check if the browser is Safari and call `insertLineBreak` from the `SplitPlugin` (when needed) by listening to the "keydown" events. (note: I was not able to find any other key combination to properly trigger the `insertLineBreak` event in Safari) opw-6413507 Forward-Port-Of: odoo/odoo#281458
Restaurant point-of-sale orders now keep combo meal items assigned to the correct course when a combo is split into individual items. Courses are also cleaned up automatically when all related items are removed, helping staff keep orders clearer and reducing kitchen confusion.
Original PR description
Following this commit: ==== - When a combo is broken down, its items are assigned to their respective courses. - Remove a course when all its items are deleted from the cart. task-6121521 Forward-Port-Of: odoo/odoo#283143 Forward-Port-Of: odoo/odoo#260276
This fix prevents certain Indian localization reports from failing when they use shared report handling logic. The B2C HSN line adjustment now only runs for the GSTR-1 report, improving reliability for other reports.
Original PR description
Currently, every l10n_in report is handled by a single handler. Therefore, a check condition is required for each report option. This check was missing in _custom_line_postprocessor, which removes the B2C HSN line conditionally. As a result, it could cause a traceback for reports other than GSTR-1. This PR fixes the issue by adding a condition to ensure that the B2C HSN line is removed only for the GSTR-1 report.
Quotation PDFs with product images now keep long product names and descriptions within their columns. This improves the readability and professionalism of sales quotes, especially when products have lengthy descriptions or unbroken text.
Original PR description
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by…
Currently, with images enabled for quotation reports and if the product name is long enough, it overflows through the column border a bit before breaking to the next line. This seems to be caused by some incompatibility between wkhtmltopdf and d-flex, adding `col` to the product name container forces it to respect column boundaries. This commit also adds `text-break` as having a long uninterupded string in the description would end up stretching the column and making the next ones disapear. <img width="811" height="266" alt="image" src="https://github.com/user-attachments/assets/90043c88-d03f-4324-9935-e669f6a256ab" /> <img width="964" height="431" alt="image" src="https://github.com/user-attachments/assets/2b8e8a6c-6fd5-4813-8160-d94bbb5490d1" /> ### Steps to reproduce: - Enable Display Product Images in the setting - Create a product with an image - Create a quotation with said product and add a description that is long enough to break to the next line - Print said quotation - You will notice that before the line breaks it will overflow to the next column (you might need to tweak the description a bit by removing or adding a few lines) opw-6367076 Forward-Port-Of: odoo/odoo#275978
Indian GST purchase reports now better reflect legal reporting requirements for imported goods and services. Imports of services are no longer shown in GSTR-2B, and GSTR-3B reporting has been adjusted to match the latest section rules.
Original PR description
As per the law, import of services is not required to be shown in GSTR-2B. Therefore, the related report lines are removed in this commit. Additionally, GSTR-3B reporting is now handled according to the updated section changes for import of goods and services. task-6330737 Forward-Port-Of: odoo/enterprise#124550 Forward-Port-Of: odoo/enterprise#121925
WhatsApp messages using templates with many mixed placeholders now send each value to the correct spot. This prevents customers from receiving messages with mismatched details when templates include 10 or more variables.
Original PR description
**Issue**:
Sending a WhatsApp template with 10 or more variables can assign values to the wrong placeholders when the body contains mixed variable types, such as free text, field, or user name variables.
Templates containing only free-text variables are not affected.
**Reason**:
Meta consumes template parameters positionally, but for mixed variable types, Odoo built the parameter list using the template variable recordset order.
That order can differ from the numeric placeholder order, notably placing {{10}}, {{11}}, {{12}}... before {{1}}
when sending the message, as the payload parameters are not ordered by their numeric placeholder index.
**Fix:**
Sort body variables by their numeric placeholder index before preparing the Meta payload.
Task-6401501
Forward-Port-Of: odoo/enterprise#128492
Forward-Port-Of: odoo/enterprise#125671German DATEV exports now handle bank settlements involving three different currencies by splitting them into compliant accounting legs. This prevents export issues and ensures each DATEV line uses only one foreign currency while leaving normal transactions unchanged.
Original PR description
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank…
Issue: - DATEV does not support multiple foreign currencies on a single journal line. - This can occur when reconciling a bank transaction where: - the payer uses one currency (C1), - the bank journal is held in another currency (C2), - the company uses a third currency (C3). - The existing export logic could not represent the bank liquidity and foreign AR/AP currencies separately in such cases. Fix: - Detect 3-currency cases from bank statement transactions and their liquidity line. - Use the DATEV clearing account (1360 SKR03 / 1460 SKR04) to split the transaction into two logical legs: - Bank → Clearing (bank journal currency) - AR/AP → Clearing (payer currency) - Emit the liquidity leg only once when multiple foreign AR/AP lines are reconciled against the same bank transaction. - Keep regular 1- and 2-currency transactions on the existing export path. Impact: - Correctly represents 3-currency bank settlements in DATEV. - Keeps each exported line in a single foreign currency. - Leaves manual entries and payment transactions outside this specific handling, as the scenario is specific to the bank liquidity line. taskID-5457547 Forward-Port-Of: odoo/enterprise#128876 Forward-Port-Of: odoo/enterprise#109010
Barcode deliveries now use the real storage location of a scanned serial number when it was not already reserved. This prevents inventory from being deducted from the wrong parent location, keeping stock counts accurate across warehouse sublocations.
Original PR description
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial…
Steps to reproduce --- 1. Enable Storage Locations and Lots/Serial Numbers. 2. Set the delivery operation type's "Source Location" to "Do not scan". 3. Create a serial-tracked product with a serial stored in a sublocation (e.g. WH/Stock/Section 2). 4. Confirm a sale order for it, open the delivery in Barcode, and scan an unreserved serial. Issue --- Scanning the unreserved serial creates a new move line that falls back to _defaultLocation() because the decoded scan carries no source location (the operation type does not require scanning one) and never carries the serial's quant location. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_model.js#L937-L944 For a delivery, that default resolves to the picking's own source location (the parent WH/Stock), so the line is sourced from the parent instead of the sublocation where the serial physically sits. https://github.com/odoo/enterprise/blob/f42cfa7265ce32bd95f7f805cf4fb54d8b79cce1/stock_barcode/static/src/models/barcode_picking_model.js#L1542-L1544 On validation the unit is deducted from the parent location instead of the sublocation, leaving a stale quant of the serial in the sublocation and a negative quant at the parent. opw-5864414 Forward-Port-Of: odoo/enterprise#128523 Forward-Port-Of: odoo/enterprise#121375
The Swiss payroll module no longer assigns a Swiss contract type by default when the employee or company context is not Swiss. This prevents incorrect employee contract information and avoids related automated test failures.
Original PR description
[FIX] l10n_ch: fix default contract type This task is runbot error fix that occured from 19.0 to 19.2 Bug reproduction: 1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute…
[FIX] l10n_ch: fix default contract type
This task is runbot error fix that occured from 19.0 to 19.2
Bug reproduction:
1 - Go to version 19.0, install l10n_ch_hr_payroll_account 2 - Execute test_version_timeline_auto_save_tour tour test 3 - It fails in .o_arrow_button_wrapper[data-tooltip^='Contract:'] step
Bug cause:
1 - When l10n_ch_hr_payroll_account is installed:
1.1 - contract type becomes "Permanent contract with monthly salary"
1.2 - the employee is not swiss but it has this CH contract type
2 - data-tooltip starts with Permanent contract instead of contract
2.1 - Tour fails
3 - contract_type_id is overwritten in swiss modules
3.1 - Default is assigned without looking to the country of self.env
Bug solution:
1 - If the country is not swiss, the default is assigned as False
1.1 -> fixed in l10n_ch_hr_payroll/hr_version
1.2 instead of assigning swiss contract type to the non-swiss emp.
Note: This is fix from saas-18.4 to master.
task-6392040
runbot error: https://runbot.odoo.com/odoo/runbot.build.error/941358
Forward-Port-Of: odoo/enterprise#127830
Forward-Port-Of: odoo/enterprise#126520Point of Sale now correctly validates negative orders that were manually paid with standard methods such as card payments. This prevents users from being wrongly blocked by a customer selection popup when the first payment option is Customer Account.
Original PR description
Validating a negative order manually paid with a standard method (e.g., Card) mistakenly triggers the fast payment fallback. The system wrongly assumed any single negative payment line was an auto-generated unsettled due. As a result, if the first configured payment method is "Customer Account", validation is incorrectly blocked by a popup asking for a customer. This commit restricts the fast payment trigger for negative amounts to only apply when the existing line is specifically a 'pay_later' type. task-6443347 Forward-Port-Of: odoo/odoo#282844 Forward-Port-Of: odoo/odoo#281238
Fixes an editor display issue where gradient-styled text inside a link could disappear when selected. Users editing website or email content can now clearly see linked text during selection, reducing confusion and editing mistakes.
Original PR description
Problem: When text formatted with `.text-gradient` is inside a link with `.o_link_in_selection`, the selected text becomes invisible. `.text-gradient` sets `-webkit-text-fill-color: transparent`, which prevents `color: black !important` on `.o_link_in_selection` from taking effect. Cause: `-webkit-text-fill-color: transparent` from `.text-gradient` overrides standard text `color` rendering, causing the text to stay transparent against the selection highlight background. Solution: Set `-webkit-text-fill-color: black` on `.o_link_in_selection` to ensure text inside gradient links is rendered in black and remains clearly visible when selected. Steps to reproduce: - Add text "ABCD". - Apply gradient color to all text. - Create a link on "BC". - Place cursor/selection inside the new link. - Observe that the text is not visible. opw-6479350 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#282952
Users on the Android mobile app can now download images and other files opened from Odoo without seeing an unsupported download error. The change sends eligible file downloads through the mobile app's supported download path, improving a visible workflow in Discuss and file viewing.
Original PR description
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads…
Steps to reproduce: - send an image in a Discuss channel - click the image to open the file viewer - click the download button => Android shows "The Odoo Mobile Apps only supports file downloads using the HTTP protocol." downloadFile()'s GET-by-URL case fetches the URL via XHR, then saves the Blob response by clicking a hidden <a download> anchor on a blob: URL. Android's DownloadManager only accepts http(s) URLs, so it rejects that blob: URL instead of downloading anything. Patch downloadFile._download to hand the URL directly to a new mobile.methods.saveFile bridge method when available, the same way download._download already delegates to mobile.methods.downloadFile. Blob/string content downloads aren't handled here — the only such call site (spreadsheet JSON export) is debug-mode only, so this is left as a console.warn for now. Related to odoo/odoo@e83fd8c08c879f5e262d39f24edcb3f81238ea82 Code made by Claude Changes supervised by HUVW Forward-Port-Of: odoo/enterprise#128471 Forward-Port-Of: odoo/enterprise#127693
Belgian payroll now avoids showing a missing transport benefit warning for company executives. This prevents an incorrect alert from appearing on executive contracts where the rule should not apply.
Original PR description
The transport benefit warning incorrectly applies to company executives (Joint Committee = 999). This warning is intended solely for regular employees. Steps to reproduce: 1. Go to an employee's contract and set the Joint Committee to 999. 2. Set a monthly wage that results in an annual salary below 34,654€. 3. Ensure no transport benefits are selected. 4. Save the contract; the missing transport benefit warning is incorrectly displayed. This change skips the validation for Joint Committee 999 to ensure the warning only triggers when applicable. task-6442880 Forward-Port-Of: odoo/enterprise#126642
Projects linked to both standard sales orders and rental orders now show the full list when users open the Sales button. This makes the displayed sales count match the actual orders shown, reducing confusion for teams managing rental-related projects.
Original PR description
Steps to Reproduce --- 1. Install sale_renting_project. 2. Create a Project linked to 1 standard Sales Order and 1 Rental Order. 3. Observe the "Sales" stat button counts 2 Sales. 4. Click the stat button. Only the standard Sales Order is displayed. Issue --- In saas-18.4, the project Sales stat button calls action_view_sos without the from_embedded_action context key. As a result, _get_sale_orders_domain applies the non-rental filter by default, causing rental orders to be excluded from the action even though they are included in the displayed counter. Expected Behavior --- The Sales stat button should display all orders linked to the project, including both standard and rental orders, matching its total counter. Fix --- Return the base project domain unmodified when from_embedded_action is not set in the context. task-6140201 Forward-Port-Of: odoo/enterprise#128468 Forward-Port-Of: odoo/enterprise#121449
Products with a base price of zero but paid attribute options are now correctly recognized as having a sellable price. This prevents shoppers from being blocked when adding these configured products to their website cart while zero-price sale prevention is enabled.
Original PR description
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never`…
Steps to reproduce: --- - Install `website_sale` module. - Enable `Product Variants` and `Prevent Sale of Zero Priced Product` in settings. - Create new attribute > set `Variant Creation` as `Never` and also add value with extra price. - Create a product with sales price = 0, assign the attribute, and publish it. - As a public user (incognito), try to add the product to the cart. Issue: --- - In terminal error `The given product does not exist therefore it cannot be added to cart` is raised. Root cause: --- - In `_is_add_to_cart_allowed()`[1], the method calls `_get_contextual_price()` [2] to check if the product's price is zero when `prevent_zero_price_sale` is enabled. - However, `_get_contextual_price()` is called without the no-variant attribute values in the context, so it does not account for their `price_extra`. For a product with list price as 0 and attribute with extra price, the price is incorrectly computed as 0, causing `_is_add_to_cart_allowed()` to return `False`. Solution: --- - Before calling `_is_add_to_cart_allowed()`, set the product's context with the no-variant attribute values via `_get_product_price_context()`, so that `_get_contextual_price()` correctly includes the price extra in its computation. [1]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/controllers/cart.py#L117-L120 [2]https://github.com/odoo/odoo/blob/bbafbbd8950ec7123ab652851ede5479484eee26/addons/website_sale/models/product_product.py#L149-L150 opw-6365566 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#283491 Forward-Port-Of: odoo/odoo#278620
The LinkedIn social integration now handles cases where LinkedIn returns no account statistics. This prevents refresh failures and helps users keep their social account data up to date reliably.
Original PR description
Bug === When the LinkedIn API returns no statistics for the account, the refresh crashes. Task-6425391 Forward-Port-Of: odoo/enterprise#126326
The AI assistant for drafting social posts no longer crashes when preparing the request context, especially when using Google-backed AI services. This helps users reliably ask AI for help writing social content without interruption.
Original PR description
Bug === The `aiChatSourceId` contains `datapoint_x`. Also, look like now we should `json.dumps` the initial context. Task-6485440 Forward-Port-Of: odoo/enterprise#124832
Fixed an issue where inserting an AI-generated image from the media dialog could cause an error. This helps users complete social post content creation smoothly without being interrupted by a crash.
Original PR description
Bug === Since odoo/odoo@7427089969ab445dc86e37d628c9c59e7c73c632 , when we open the media dialog, click on the AI button, generate an image and then insert it, a traceback is raised. Task-6432288 Forward-Port-Of: odoo/enterprise#126229
This update standardizes how Odoo builds and runs database queries across many apps, reducing maintenance risk and helping prevent query mistakes. Most changes are internal, but they support more reliable behavior in areas such as accounting, CRM, events, HR, mail, purchasing, and marketing.
Original PR description
Detected usages by a new linter for SQL. https://github.com/odoo/enterprise/pull/128045 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update standardizes how many Odoo modules retrieve and prepare data behind the scenes, especially in accounting, reporting, documents, payroll, helpdesk, knowledge, and marketing-related areas. It should make the codebase easier to maintain and reduce the risk of inconsistent database behavior, with limited direct impact on day-to-day users.
Original PR description
https://github.com/odoo/odoo/pull/282652
This change modernizes the internal way Odoo handles popovers, bottom sheets, and dialogs while keeping existing compatibility in place. Users should not see major behavior changes, but the update helps make these interface elements easier to maintain and evolve.
Original PR description
In this commit, we rewrite the popover, bottom_sheet and dialog services as plugins. For legacy purposes, we keep the popover, bottom_sheet and dialog services (as services). We also adapt the codebase to reflect the changes on the services.
The way Odoo manages popovers, bottom sheets, and dialogs has been modernized behind the scenes. This helps keep the web interface easier to maintain while preserving existing behavior for users and older customizations.
Original PR description
In this commit, we rewrite the popover, bottom_sheet and dialog services as plugins. For legacy purposes, we keep the popover, bottom_sheet and dialog services (as services). We also adapt the codebase to reflect the changes on the services. Community: https://github.com/odoo/odoo/pull/281432
Web view URLs now keep only the search filters the user actively applied, instead of storing extra internal page details. This makes shared or saved links lighter, clearer, and less likely to expose unnecessary technical information while keeping search behavior consistent.
Original PR description
Only the search performed by the user (the active facets) needs to end up in the url, not the whole internal state of the view. Pushing the complete state was heavier than necessary and leaked more detail into the url than a search really is. A lightweight representation of "what the user searched for" already existed, introduced for reapplying a search when working offline. Reusing it here avoids maintaining two different ways to describe a search, and pushed us to make that representation a bit more robust so it can be trusted for both purposes. Finally, deciding what belongs in the url is the search model's responsibility, not the action service's: the model is the one that actually knows what a facet is. Moving that decision there removes an indirection the action service had no real reason to carry.
A contributor has submitted their Individual Contributor License Agreement for Odoo. This is a legal housekeeping update that helps ensure future contributions can be accepted under the project’s licensing requirements.
Original PR description
This pull request submits my Odoo Individual Contributor License Agreement signature. Forward-Port-Of: odoo/odoo#282045