Friday, August 28, 2026
84 changes · master
Security fixes and vulnerability patches
When a production database is neutralized for testing, debugging, or sharing, stored outgoing email usernames and passwords are now cleared. This reduces the risk of real email relay credentials being carried into copied databases while keeping email sending blocked as before.
Original PR description
### Impacted versions 19.0 (the same applies to every branch shipping `base/data/neutralize.sql`) ### Steps to reproduce 1. On a database with an outgoing mail server configured with a username and…
### Impacted versions 19.0 (the same applies to every branch shipping `base/data/neutralize.sql`) ### Steps to reproduce 1. On a database with an outgoing mail server configured with a username and password, neutralize it (`odoo-bin neutralize`, or restore/duplicate with neutralization enabled). 2. Look at the `ir_mail_server` row. ### Current behavior The server is archived, so the database can no longer send. `smtp_user` and `smtp_pass` are left untouched, so the credentials stay in the database and travel with every dump taken from it. The password still authenticates against the real relay. ### Expected behavior Neutralization is what turns a production database into one that can be copied and handed around — a staging build, a dump downloaded for debugging. A database that is not allowed to send mail has no use for a credential to send it with, and keeping it means the credential leaves the platform with the copy. ### Fix Clear `smtp_user` and `smtp_pass` in the same statement that archives the servers. The stub relay inserted just below still blocks the fallback to the command-line SMTP settings, so behavior is unchanged otherwise. Tested by seeding a mail server with credentials, running the file, and checking the row: archived, credentials empty, stub relay present. Forward-Port-Of: odoo/odoo#284960
New functionality added to Odoo
Managers can now drag or resize time off entries directly in the calendar instead of opening each request and editing dates manually. The system keeps changes aligned with each leave type's rules, asks for confirmation when approved leave is changed, and reverts updates that fail validation.
Original PR description
Description of the issue/feature this PR addresses: Time off can only be rescheduled by opening the leave form and editing its dates by hand — the calendar is read-only, which is slow for managers…
Description of the issue/feature this PR addresses: Time off can only be rescheduled by opening the leave form and editing its dates by hand — the calendar is read-only, which is slow for managers who plan visually. Current behavior before PR: Leave events on the Time Off calendar cannot be moved or resized. Changing a leave's dates requires opening the record and editing request_date_from / request_date_to (and the AM/PM period or hours) manually. Desired behavior after PR is merged: Leave events can be dragged and resized directly on the calendar. The dragged result is snapped server-side to the leave type's request unit: - day: move/resize by whole days; - half_day: endpoints snap to the AM/PM boundary; - hour: move anywhere, resize on the time grid in hours. Editing is gated by the new can_reschedule field so approval rules are honoured; rescheduling an approved leave asks for confirmation and resets it to "To Approve", and a backend rejection (e.g. an allocation error) reverts the event. task-4809240 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Enhancements to existing features
Odoo now handles very large groups of records more efficiently by deciding when to reduce automatic preloading based on the original list size. This should lower unnecessary database work and improve performance in areas that process many records, such as accounting, mail, point of sale, exports, website, and attachments.
Resolved issues and error corrections
Timesheet suggestions created from calendar events now better match the correct project or task and display adjusted event durations correctly after overlaps are resolved. This helps users log time with fewer manual corrections and reduces confusion from inaccurate suggested entries.
Original PR description
task: 6435164 Forward-Port-Of: odoo/enterprise#126680
Features or functions removed from Odoo
This removes outdated checks and references for old module setup file options that no longer worked in regular modules. The change reduces confusion for maintainers and keeps Odoo's module handling aligned with current supported behavior, with no expected impact for everyday users.
Original PR description
- forgot I already did a pass back in #215533 so just remove the mentions of `init_xml`, it was deprecated for 19.0 and was just a notice as it had not worked for more than a decade before then - also remove the check on `demo_xml` which hasn't worked or done anything useful since dfb9d317f269810c8e857a7bc898389242ac9fa7 either (same as all the other `_xml` keys as that uwittingly broke them all) Note that the `init_xml` = csv(noupdate) works in data modules (`base_import_module`), because when fme implemented that he missed that it had stopped working (for only a few months at that time) in normal modules. It was not deprecated in #215533 either since it worked fine and there was no easy way to feed that information back to data module, and we don't know whether this is ever used by anyone.
Code cleanup and technical improvements
This update restructures how mail and chat data is calculated and refreshed behind the scenes, reducing unnecessary recalculations and making state changes more predictable. It also fixes several issues found during the cleanup, including attachment typing, pinned chat behavior, and missing CRM typing declarations.
Original PR description
Commit 1. Before this commit, `Record.onChange` binds its two functions to what `this` is at the call site. A record is only reachable as its proxy once the constructor is over, so a registration has…
Original PR description
The previous approach was splicing the recordset in the __iter__ into batches of record with prefetch_ids equal in size to PREFETCH_MAX. This resulted in the iterator not being able to differentiate…
The previous approach was splicing the recordset in the __iter__ into batches of record with prefetch_ids equal in size to PREFETCH_MAX. This resulted in the iterator not being able to differentiate whether it comes from a large recordset or not. Which made the caching method to be used for this recordset not known as we dont have enough information on the recordset when it reaches the fetch. This made way for a lot of ad hoc fixes to detect earlier when the recordset is big enough to disable the prefetching. Currently, the slicing is removed so checking on the size of the original recordset can be done directly with getting the size of the prefetch_ids. This means that we can disable the prefetching for large recordsets on the fly without needing to change the context on a specific recordset. This also allows us to have a smaller callstack and lower number of queries per recordset. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The employee Overtime button now opens a pivot table instead of a collapsed list, making overtime information visible immediately. This helps payroll and HR users review overtime by type and month without manually expanding grouped records.
Original PR description
The employee's "Overtime" smart button opened an hr.leave list view grouped (collapsed) by year then type, so nothing was visible until every group was manually expanded. This commit replaces it with a Pivot view (work entry type rows, month columns, duration in hours as measure) and swaps the old group-by search defaults for the search view's existing "this year" filter default, so the button actually shows data on open. Task 6498778
This update improves how large sets of records are handled during German DATEV CSV exports. It helps reduce unnecessary system load, making large exports more efficient and reliable for businesses processing significant accounting data.
Spreadsheet pivots now prevent users from inserting configurations that rely on unsupported relation fields with non-numeric IDs. This avoids broken pivot tables and guides users with clearer disabled controls and tooltips.
Original PR description
Prevent inserting a pivot into a spreadsheet when it contains groupbys on relations whose IDs are not numeric (e.g. account.root uses string IDs), as the pivot table engine does not support them. The insert button is now disabled with an appropriate tooltip, and the layout configurator filters out blacklisted relations from the dimension field selector. Task: 6023622
Priority fields in list views now show only the selected stars by default, reducing visual clutter for records with low or no priority. Users can still see the full priority scale by hovering over the field, keeping the interface cleaner without removing context.
Original PR description
Before this change, priorities in list views always displayed all stars, including empty ones. Records with low or no priority showed multiple empty stars, creating unnecessary visual clutter. After this change, only filled stars are displayed by default. Records with no priority show a single empty star, and hovering over the priority field reveals the complete set of stars. task-6365816 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update improves how company configuration is shared across branch structures in Odoo. It helps businesses keep related branches aligned with common settings, reducing duplicate setup and making administration more consistent.
Original PR description
task-6341281 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
Accounting dashboard KPI cards now display at consistent sizes on tablet and desktop screens. This makes the dashboard easier to read and prevents cards from stretching awkwardly when the layout wraps.
Original PR description
Currently, the KPIs wrap around for tablets and don't render correctly This commit makes them render with the same size. It also stops cards from growing when they wrap on desktop screens. No task ID
The mail test helper now re-checks pending conditions every 500 milliseconds instead of waiting until a long timeout when certain screen changes are not detected. This reduces avoidable waiting in the mail test suite and helps developers get faster validation without changing customer-facing behavior.
Original PR description
Before this commit, a contains that does not match right away runs again only when its MutationObserver fires, and once more at the 10 seconds timeout. The problem is that the observer reports neither a text node updated in place nor an input value or checked property, so a check waiting for one of those sleeps 10 seconds and then passes: "Delete starred message decrements starred counter once" spends 10.2s of the 183s @mail suite waiting for a counter to go from "Starred3" to "Starred2". This commit turns that single timeout into a 500ms tick up to the same deadline, so that such a check costs 500ms. The tick uses the unmocked timer to stay out of the timer graph a test drives with runAllTimers, and only 32 of the suite's 4239 contains calls stay pending long enough to tick once. Forward-Port-Of: odoo/odoo#285129 Forward-Port-Of: odoo/odoo#284944
Belgian payroll settings can now be shared more consistently across company branches. This reduces duplicate setup work and helps keep payroll configuration aligned for businesses operating with multiple branches.
Original PR description
task-6341281
Employees who join after the BPJS Kesehatan billing cut-off will no longer have that contribution taken from their first payslip. The missed amount is tracked as arrears so it can be included in a later payslip, improving payroll fairness and accuracy.
Original PR description
Employees who join after the BPJS Kesehatan billing cut-off should not be charged on their first payslip. Any missed contribution is carried forward as arrears and can be included on the following payslip. task-6002251
The payroll dashboard now shows warning cards much faster by reusing the last known browser-saved state while updated checks run in the background. It also fixes a crash that could happen after dismissing all warnings when upcoming pay run dates were displayed.
Original PR description
Payroll warnings on the dashboard were loaded one by one, blocking the page until every warning finished computing and giving a poor first-load experience. Warnings now render instantly from the…
Payroll warnings on the dashboard were loaded one by one, blocking the page until every warning finished computing and giving a poor first-load experience. Warnings now render instantly from the browser's local store of the last known state, while the real computation still runs per warning in the background: - On a fresh browser, warnings load progressively as before, and get stored locally once computed. - On a later visit, stored warnings appear instantly with a spinner while they recompute in the background. - Once recomputed, a card updates in place, fades out if no longer valid, or fades in at the correct date if newly valid. Bug fix:- Steps to reproduce:- 1. Set schedule on payroll dashboard. 2. Dismiss every warning. 3. On dismissing last warning throws a traceback. Root cause:- `DashboardEmptyScreen` passed the raw closing_date value straight from the RPC response into formatDateLabel, which calls date.diff(...) assuming a Luxon DateTime. The RPC layer serializes it as a plain ISO string, so formatDateLabel crashed with "date.diff is not a function" any time the empty-dashboard screen rendered with upcoming pay runs. Fix:- added new method `formatClosingDate` to format `closingDate` seperately. task-[6240120](https://www.odoo.com/odoo/project/1251/tasks/6240120)
Assistant Rules screens for timesheets have been redesigned to make them easier to read, search, and manage. The update improves consistency across list, kanban, form, and search views, with supporting cleanup that should make the feature more reliable and maintainable.
Original PR description
This PR overhauls the list, kanban, form and search views of the Assistant Rules for clarity and consistency, along with a few related fixes and cleanups on the `aw.rule` model. Task-6116508
New project document folders now automatically inherit the available actions configured on their parent folder, making setup easier across projects. Folder access is also aligned with project visibility, and internal project followers are synchronized as folder members when visibility changes.
Original PR description
- This commit makes the newly created project's document folder have the parent folder's available embedded actions enabled by default. It is done to easily enable actions for all the project folders. - The visibility of the project impacts the internal access of the related folder. Here is the mapping of the project's visibility with the document's rights: | Visibility | Internal Access | |--------|--------| | Invited Internal Users | None | | Invited Internal and Portal Users | None | | All Internal Users | Editor | | All Internal Users and Invited portal users | Editor | Also, when the project's visibility changes, the members of the related document folder are also synchronized with the project's internal followers users. Task-6025723
Turkish payroll has been updated to apply the 2026 SGK social security contribution rules, including new minimum and ceiling checks for the SSI contribution base. The change also simplifies how employee and employer contributions are calculated and lets companies apply the relevant employer incentive reduction.
Original PR description
Update Turkish payroll localization to reflect 2026 SGK regulatory parameters and restructure SSI contribution rules: - Consolidate employee SSI contribution (Disability 9%, Health 5%, Short-Term 0%, Unemployment 1%) under a single salary rule (SSIEDED). - Consolidate employer SSI contribution (Disability 12%, Health 7.5%, Short-Term 2.25%, Unemployment 2%) under a single salary rule (SSICDED). - Remove obsolete standalone unemployment salary rules (SSIDED and SSIUCDED) and their related rule parameter. - Add SSI base amount minimum and update the SSI base ceiling rule parameters, and clamp the SSI contribution base between them. - Add l10n_tr_incentive_tier field on res.company and res.config.settings (0, 2, or 5 points) to deduct incentive points from the employer SSI contribution rate. **task-6397284**
Belgian payroll now better supports economic unemployment compensation, including specific handling for CP302 and clearer separation for CP200 employees. This helps payroll teams apply the right compensation rules and receive a reminder when required inputs are missing.
Original PR description
This commit adds the rules to support economic unemployment for CP302 and updates the existing setup. Key changes: * Add the 'ECONOMIC_UNEMPLOYMENT_BASE' category to better group economic and temporary unemployment rules. * Split the EUC rule into two separate rules: - 'EUC_CP200': For CP200 employees (uses a property input). - 'EUC': For all other joint committees. * Add a warning for 'EUC_CP200' to remind the user to set the input, which defaults to 0.0. * Rename the 'EUB' and 'EUT' rules to fit the new changes, and include the necessary upgrade script. * Add tests for the new rules and calculations. Task #6365138
Two Belgian payroll rules now use the correct employer detail category for social security reporting. This helps keep payroll declarations aligned with expected reporting structure without changing payroll calculation logic.
Original PR description
The following rules (code): - ONSSELDERLY - ONSSEMPLOYER_ARTIST_REDUCTION must have ONSSEMPLOYERDETAIL as a category. Updated the category_ids field of those rules to implement it. task: 6510619
Deleting accounts in the German reports module should now complete more quickly in cases with large amounts of related accounting data. The change adds supporting database indexes so the system can verify account usage more efficiently before deletion.
Original PR description
Without these indexes, the foreign key check when deleting an account can take a long time. Forward-Port-Of: odoo/enterprise#129403
Deleting an account now benefits from added database indexes in Accounting and Point of Sale. This reduces delays caused by background dependency checks, improving responsiveness for users managing account records.
Original PR description
Without these indexes, the foreign key check when deleting an account can take a long time. Forward-Port-Of: odoo/odoo#284780
Duration values are now formatted consistently across planning, Gantt, and grid views. This improves readability for users reviewing scheduled time and reduces inconsistencies in how time spans appear.
Original PR description
Replace formatFloatTime by formatDuration.
HR users can now see which employees and material resources are linked to a working schedule directly from smart buttons. When a schedule is shared across employees, the system warns users and offers to duplicate it for the current employee, reducing accidental changes that affect multiple people.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: . Add a smart button that list the employees linked to the working schedule . Add a smart button that list the material resources linked to the working schedule . Show a “Shared Across Employees” warning when navigating from the Employee model, with an option to duplicate and edit the record for the current employee, automatically linking the newly created record to that employee. task-6106525 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Turkish Nilvera e-invoice users no longer need a separate step to retrieve the official PDF once an invoice is accepted. The status sync now also fetches the PDF for successful invoices, handles additional successful commercial invoice statuses, and allows retrying sync when the status is unknown.
Original PR description
Getting the official Nilvera PDF on an invoice took three steps: wait for the status cron to run, wait for the invoice to be accepted by GİB, then click "Fetch Nilvera e-invoice PDF". The sync button…
Getting the official Nilvera PDF on an invoice took three steps: wait for the status cron to run, wait for the invoice to be accepted by GİB, then click "Fetch Nilvera e-invoice PDF". The sync button next to the Nilvera status only refreshed the status and stopped there, so the user had to come back to the invoice later for the document itself. Fetch the PDF right after the status refresh for the invoices that came back successful, and drop the now redundant button from the form view. Pending invoices are filtered out beforehand so they are not polled a second time by the PDF routine. A commercial invoice does not stay on 'succeed'. Once GİB accepts it and the recipient answers, the status is overwritten with 'commercial_approved' or 'commercial_answered_automatically', and both are terminal successes. Group the three in a constant and use it at every PDF gate. In the PDF routine those invoices previously matched none of the status branches, so they were dropped without being fetched, reported pending or reported failed. 'commercial_rejected' stays out: a rejection is not a success, and its PDF is already fetched by the rejection handler. Also show the sync button when the status is "Unknown": e-archive invoices stay unknown until GİB generates its report at 20:00 GMT+3, which is precisely when the user wants to poll again. The status cron already covers that status, the view was the odd one out. task-6434404 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Spreadsheet users can now create a new global filter directly from the related filters area in the side panel. When a field is selected, the filter editor opens with relevant fields already filled in, reducing manual setup and making spreadsheet filtering faster.
Original PR description
Task: 6079698
Website editors can now preview the AI live chat fallback button by hovering over the option before enabling it. This makes it easier to understand how the button will appear on the website and choose the right configuration with confidence.
Original PR description
Before this commit, there was no preview available of the ai livechat's fallback button. After this commit, a user will be able to hover over "Fallback Button" and see a preview of what the button would look like before enabling it. task-5248712
Belgian accounting tax data now marks additional 0% taxes with the non-deductible fiscal position where it was missing. This helps companies using Belgian localization apply tax treatment more consistently and reduces manual correction in accounting setup.
Original PR description
Adding non-deductible fiscal position to taxes that were missing it in the data. task-6389423 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284869 Forward-Port-Of: odoo/odoo#278020
Turkish e-Archive invoices can now identify e-commerce sales and include the required payment, website, shipment, and delivery details. This helps businesses comply with GiB requirements and prevents invoice export when mandatory e-commerce information is missing.
Original PR description
Purpose: Turkiye e-Archive regulations require invoices generated from e-commerce sales to include specific tracking and fulfillment information. Previously, the system did not distinguish between…
Purpose:
Turkiye e-Archive regulations require invoices generated from e-commerce sales
to include specific tracking and fulfillment information. Previously, the system
did not distinguish between standard sales and e-commerce sales, which is
required by GiB.
Modifications:
-Introduced stored computed field `l10n_tr_sales_type`('normal', 'website') on
'account.move', allowing users to control whether e-commerce nodes are included.
-Made `l10n_tr_sales_type` and `l10n_tr_gib_invoice_type` required when
`l10n_tr_nilvera_customer_status = 'earchive'`.
-Updated e-Archive XML generation to automatically inject required e-commerce
nodes when `l10n_tr_sales_type` is set to 'website'.
-Added validation checks to block export if required e-commerce details are missing.
Key additions for e-commerce sales include:
-Identifies the order as e-commerce sale and includes specific website domain.
-Adds payment details such as agent name, method used (e.g., Credit Card, Wire
Transfer, Payment Provider), and payment date.
-Includes logistics data like carrier/driver name, Tax ID (VKN/TCKN), and
shipment/delivery date.
Related Upgrade PR: https://github.com/odoo/upgrade/pull/10981
task-6236315The HR module now makes its clean number display component available for reuse in other Odoo editions. This helps Enterprise extend HR screens to show decimal values with custom unit labels, such as days, while keeping formatting consistent.
Original PR description
Export `FloatWithoutTrailingZeros` and `floatWithoutTrailingZeros` from the `hr` module so they can be imported and extended in Enterprise to support float fields with custom unit suffixes (e.g., "Days"). Task: 6222665 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update adds checks to ensure payroll rule data files are kept up to date for several country localizations. It helps reduce payroll configuration inconsistencies and supports more reliable payslip processing in Bangladesh, Kuwait, Indonesia, Iraq, Oman, Romania, and Pakistan.
Original PR description
. Add check that the rules data files are updated on localizations . Add _get_data_files_to_update() method for bd, kw, id, iq, om, ro, pk localizations task-6456276
This update improves the website shop pickup experience by refining how warehouse pickup locations and exceptional closing information are shown. Customers should get clearer information when choosing where to collect an order, reducing confusion and support questions.
Original PR description
Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Holiday pay payslips now hide day-tracking details that are not useful in the salary computation view, making the screen easier for payroll users to read. Related time-off values are also clearly labeled in days, reducing confusion when reviewing Belgian payroll calculations.
Original PR description
This commit improves the user experience with the following changes: - Hide "Right to time off", "Time off already taken", and "Additional Vacation Taken" inputs from the "Salary Computation" tab on Holiday Pay N and N-1 payslips. - Set the display visibility rule for these fields to "Never". - Add a "Days" unit to the "Time off", "Right to time off", and "Additional Vacation Taken" rules. Task: 6222665
Notifications have been refreshed to be smaller, clearer, and easier to follow. A new progress bar shows when a notification will disappear, improving the user experience across several Odoo apps.
Original PR description
A big part of the notification behaviour that was in the notification service has been move to the component "Notification". With this comes also a visual cleaning of the notification. Smaller, more compact and with a progress bar that show when the notification will disappear. TASK-ID: 4334047
The Manufacturing Order Overview now includes subcontracted production details, making it easier for users to understand outsourced manufacturing steps alongside regular production information. This improves visibility for teams managing subcontracting through purchase and manufacturing workflows.
Original PR description
Handle subcontracted productions in MO Overview. task: 5225952 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This update simplifies the data used by the Manufacturing Order Overview by removing an unnecessary currency field. It helps keep the report data cleaner and reduces the chance of redundant information being handled behind the scenes.
Original PR description
Remove 'currency_id' from dict task: 5225952
Manufacturing planning now supports scheduling work orders backwards from a required finish time, helping teams plan production around delivery or completion deadlines. If the calculated start time would be in the past, the system automatically switches to forward scheduling from the current time to keep plans realistic.
Original PR description
Implement backward scheduling Allow to schedule workorders 'backward': the last workorders in chain must finish at a specific datetime. However if any of the first workorders should have been started in the past scheduling is done 'forward' from now on task: 4504976 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
UPS shipping has been updated to use UPS's newer API by default because the older UPS connection is being retired. This helps keep shipping rates, labels, and related UPS services working after the legacy cutoff date, with module naming and data updated accordingly.
Original PR description
The UPS 'legacy' API will no longer be usable after 5/31/2024 So make UPS 'rest' API the default
Manufacturing order overviews now include a planning simulation that considers work center availability, similar to the existing bill of materials overview. This helps business users assess scheduling feasibility earlier without changing component availability assumptions.
Original PR description
Simulate planning in MO Overview task: 4455170 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a spacing issue where date picker popups could lose their normal padding because of a calendar side panel adjustment. The padding change is now limited to the calendar side panel, keeping popups visually consistent elsewhere.
Original PR description
- requires https://github.com/odoo/odoo/pull/284964 The template override forced `pb-2` on every picker so it would sit flush in the calendar side panel, stripping the padding from popovers too. Set `--DateTimePicker-padding` on the panel instead. task-6512183
This fix restores the expected horizontal spacing around date pickers shown in popovers, making them easier to read and use. Calendar side panels can still keep their tighter layout without affecting date pickers elsewhere.
Original PR description
- requires https://github.com/odoo/enterprise/pull/129503 | //////// | Calendar C.E (identical) | Calendar E.E (preserve top alignment) | Datepicker (restore padding) | Frontend datepicker |…
- requires https://github.com/odoo/enterprise/pull/129503 | //////// | Calendar C.E (identical) | Calendar E.E (preserve top alignment) | Datepicker (restore padding) | Frontend datepicker | |--------|--------|--------|--------|--------| | Master | <img width="466" height="497" alt="image" src="https://github.com/user-attachments/assets/148943b7-c89d-4aec-8b9a-fdf8e58016e2" /> | <img width="487" height="536" alt="image" src="https://github.com/user-attachments/assets/5d09bcd4-a3d4-475b-b97f-02a2254398da" /> | <img width="453" height="418" alt="image" src="https://github.com/user-attachments/assets/fa815751-50de-4257-8b25-81801042c4ce" /> | <img width="616" height="451" alt="image" src="https://github.com/user-attachments/assets/9c4a646c-d1be-4431-afd6-552ab3e84e62" /> | | This PR | <img width="455" height="488" alt="image" src="https://github.com/user-attachments/assets/2957ae2e-32c2-40b1-906a-bf643f1c6028" /> | <img width="488" height="498" alt="image" src="https://github.com/user-attachments/assets/09f66532-45e0-4a73-9133-94ba9561f3d9" /> | <img width="574" height="407" alt="image" src="https://github.com/user-attachments/assets/1bd5cb86-0adc-46ed-8f52-421e103261f1" /> | <img width="602" height="437" alt="image" src="https://github.com/user-attachments/assets/2c06d43c-81db-4b78-bc77-20e3d39cc2f6" />| The calendar refresh narrowed the picker's padding globally (`p-2` -> `py-2`) so it would sit flush in the calendar side panel. A later commit moved that side panel restyling to Enterprise but left the narrowed padding behind, leaving every popover picker without its horizontal spacing. Expose the padding as `--DateTimePicker-padding`, defaulting to the original spacing, and let the side panel opt out. A variable rather than a utility class also removes the `!important` the bottom sheet needed to beat `p-2`. task-6512183 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
This fixes a small internal cleanup issue in the bus messaging system by removing empty database tracking entries when they are no longer needed. It does not change user-facing behavior, but keeps background bookkeeping tidier and avoids stale internal records.
Original PR description
`_drop_topic_if_empty` discards a topic from its dbname's set but never removes the dbname key once the set becomes empty, leaving a stale empty set if no notify is ever received for this DB. No impact on the dispatch code, just a bookkeeping cleaning.
This fix updates an internal social CRM test so it no longer depends on a generic customer name that can appear in other sample data. It helps keep automated checks stable and reduces false failures during development and release validation.
Original PR description
The social CRM conversion test creates a partner named "John Doe" and expects the post-to-lead wizard to automatically match it. This relies on "John Doe" being unique in the database. Since `pos_restaurant.customer_1` is also named "John Doe", the wizard's `name_search()` can return multiple partners depending on the modules already installed when the test is run. In that case, the wizard correctly considers the match ambiguous and leaves `partner_id` empty, causing the test to fail. This commit uses a test-specific author name instead, ensuring that the test actually provides the single matching partner described by its docstring and does not depend on unrelated demo data or module installation order. [error-243065](https://runbot.odoo.com/odoo/error/243065) Forward-Port-Of: odoo/enterprise#128119
Customers can no longer set optional products on sales orders to negative quantities through the portal. This keeps customer-facing order changes consistent and prevents invalid quantities that should only be handled by sales staff when needed.
Original PR description
Since the fusion of `sale.order.option` model into `sale.order.line` model, the optional products (editable from portal) lines are not deleted when reaching a quantity of 0 or below. This could allow some customers to set negative quantities, which makes no sense as it's only something that should be set by the salesman if necessary. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr Forward-Port-Of: odoo/odoo#284493
Planning notification emails now show action buttons with a visible colored background, so employees can clearly read and click options like viewing their planning. This prevents confusion when shifts or schedules are published and helps employees respond from email more reliably.
Original PR description
Before this change: When publishing a shift or schedule, the buttons "Assign me this shift", "I am unavailable", and "View your planning" inside the notification email sent to the employee appears invisible. The button text is rendered in white on a white background, making the link unreadable and difficult to click. To reproduce: 1. Open the Planning app and create a shift with today's date in the time range. 2. Click "Publish". 3. Go to Settings > Technical > Email > Emails. 4. Open the email that was just sent. 5. Inspect the email body and observe that the "View your planning" button text is not visible. After this change: A default purple background is applied to the button, ensuring the white text is properly visible and legible across email clients. opw-6483147 Forward-Port-Of: odoo/enterprise#128662
Website links that open in a new tab are now handled in a way that better supports screen reader users. This helps visitors understand when navigation will leave the current page context, reducing confusion and improving accessibility.
Original PR description
Screen readers generally do not automatically announce that a link opens in a new tab when a user navigates to it, creating a potential barrier for non-visual users who may become disoriented if the current page is replaced without warning. Commit 2135b3c1a89c3ba0887191f36b5d73d08682f4b6 already fixed it, but this new approach follows more closely the Interaction framework.
Certification content in eLearning courses now displays correctly outside fullscreen mode. This ensures learners can access certification lessons consistently in the standard course view.
Original PR description
**Steps to reproduce:**
- Install website_slides_survey module
- Create a course in eLearning
- Add content with type Certification
- Go to the website and open the content
- It renders properly in fullscreen
- It displays nothing in the normal view
**Issue:**
`<xpath expr="//div[hasclass('o_wslides_lesson_content_type')]` targets the wrong `<div>` since [1] (it adds the certification content inside the `t-if="slide.slide_category == 'infographic'"`)
**Fix:**
Match the `t-else` condition as well for the xpath.
Fix in master as view update is needed.
[1] https://github.com/odoo/odoo/commit/e3389e392e3ccf0061e3838923ad9a9b4ea41cdd
opw-6070973This change makes automated checks for the HTML editor behave consistently across different Odoo editions. It reduces false test failures, helping development and release validation proceed more reliably without changing end-user features.
Original PR description
This PR aims to fix the failing contrast tests in the community version. The failures occur because `this.defaultBg` in contrast_plugin.js has different values in community and enterprise versions, resulting in different color contrast values. This PR fixes the tests by patching `--o-control-panel-background-color` css variable with a hardcoded value. runbot: 946513 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Scrolling or zooming within the image cropper now keeps the user’s selected crop area instead of resetting it. This prevents accidental loss of cropping adjustments and makes image editing more predictable in the HTML editor.
Original PR description
Problem: When scrolling on an image inside the image cropper (which triggers a zoom event), the selected cropping area is reset back to default instead of preserving the existing crop selection. Cause: The `t-on-zoom` event listener called `onCropZoom()`, which executed `resetCropBox()`. This called `cropper.clear()` and `cropper.crop()`, clearing and resetting the crop box whenever a zoom/scroll event occurred. Solution: Remove `onCropZoom` and `resetCropBox` so zooming or scrolling on the image does not reset the active crop box selection. Steps to reproduce: - Insert a large image in the editor. - Crop it. - Reopen the image cropper on the image. - Scroll on the image. - Observe that the selected cropping area is reset instead of preserved. task-6488910 --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Invalid VAT warnings now preserve and display the exact VAT number entered by the user, such as Swiss values like CHE-115.391.649. This avoids confusing truncated messages and helps users identify and correct the original input more easily.
Original PR description
Before this change: When entering or importing a VAT number (e.g., CHE-115.391.649), an invalid VAT warning displays a string missing its country_id (e.g., E-115.391.649). This confuses users and masks the actual input string that triggered the validation failure. To reproduce: 1. Open any contact record and set the Country to Switzerland. 2. Enter an invalid or manually formatted Swiss VAT number like `CHE-115.391.649`. 3. Save or trigger the VAT validation check. 4. Observe the warning banner showing `E-115.391.649` instead of `CHE-115.391.649`. After this change: The validation warning logic preserves the original user input when constructing the alert message, ensuring error notifications accurately display VAT number. Issue introduced by: * https://github.com/odoo/odoo/commit/ac95d2d6d80a368dfb190d0ac21da2af479a8488 * https://github.com/odoo/odoo/commit/a2afe3292e1cd0a4f339dc47707e469653d13ea0 opw-6474217 Forward-Port-Of: odoo/odoo#284305
This fix prevents duplicate emails from being sent when expenses are submitted across multiple companies. It helps keep expense notifications accurate and avoids confusing employees or approvers with repeated messages.
Original PR description
Fix a small issue resulting in mail duplication when submitting expenses from multiple companies that appeared in the infamous 704a5a19 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#284861 Forward-Port-Of: odoo/odoo#283013
This fix stops users from marking the main website menu as a mega menu when it already contains child menus. It prevents migration failures and keeps website navigation settings consistent for sites using apps such as recruitment.
Original PR description
Issue: ------- After the fix: https://github.com/odoo/odoo/commit/f1557211d9e7f83761bb36e4800e4c2f62b234c5 we can't create a child menu for a mega menu or a menu can't be a mega menu when there's an…
Issue:
-------
After the fix:
https://github.com/odoo/odoo/commit/f1557211d9e7f83761bb36e4800e4c2f62b234c5 we can't create a child menu for a mega menu or a menu can't be a mega menu when there's an existing child menu except the case of top level menu i.e; (url: /default-main-menu) and that menu will have no parent_id obviously...
Now, as per the above pr conditions the top level can be set as mega menu since it has no parent id. And in version 17.3 in the pr https://github.com/odoo/odoo/commit/47af533e9f5f721b63570d3b301951f3855384a1 a 'Jobs' menu is being created and its parent_id refers to that top level menu which we have set as mega menu. And when the records gets validated during migration the database will get blocked.
Solution:
-----------
Restrict the user by throwing the same user error, when checking/selecting the top level menu as mega menu since it has existing child menus.
Step to reproduce:
-----------------------
1. Create a database in version 17.0 with 'website_hr_recruitment' installed.
2. Go to website menus, set a top level menu(/default-main-menu) as mega menu.
3. Migrate the database to version 18.0 or more.
Traceback:
```
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 5297, in _create
records._validate_fields(name for data in data_list for name in data['stored'])
File "/home/odoo/src/odoo/18.0/odoo/models.py", line 1636, in _validate_fields
check(self)
File "/home/odoo/src/odoo/18.0/addons/website/models/website_menu.py", line 95, in _validate_parent_menu
raise UserError(_("A mega menu cannot have a parent or child menu."))
odoo.exceptions.UserError: A mega menu cannot have a parent or child menu.
File "/home/odoo/src/odoo/18.0/odoo/tools/convert.py", line 603, in _tag_root
raise ParseError('while parsing %s:%s, somewhere inside\n%s' % (
odoo.tools.convert.ParseError: while parsing /home/odoo/src/odoo/18.0/addons/website_hr_recruitment/data/config_data.xml:13, somewhere inside
<record id="website_menu_jobs" model="website.menu">
<field name="name">Jobs</field>
<field name="url">/jobs</field>
<field name="parent_id" ref="website.main_menu"/>
<field name="sequence">59</field>
</record>
```
Ref Images:
Before Fix:
<img width="1598" height="599" alt="image" src="https://github.com/user-attachments/assets/ef719945-a11b-4134-97f8-4b583c4ea6bc" />
After Fix:
<img width="1582" height="633" alt="image" src="https://github.com/user-attachments/assets/da326e45-0de8-4d42-ad47-845bfaedc84e" />
OPW - 6094298
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#280458
Forward-Port-Of: odoo/odoo#263025This fixes an error that appeared when users tried to generate a new serial or lot number for components during a manufacturing barcode operation. Manufacturing teams can now continue barcode workflows without being blocked by this issue.
Original PR description
When generating a serial/lot number in a manufacturing opperation in barcode you get an error. Steps to reproduce: 1. Create a new manufacturing picking for a product with component 2. For the components try to generate a new serial number by clicking the + button 3. An error message shows up
This fix restores the ability to set holiday table values through payroll rule parameters instead of always calculating them automatically. It matters because companies can keep different values for different employees when Mexican payroll requires that flexibility.
Original PR description
In this PR: odoo/enterprise#120199 We replaced the rule parameter for the holiday table by a method to get it automatically. The problem is that the user might want to have different values for different employees. Task: 6512040
Belgian payroll now correctly validates temporary economic unemployment leave that lasts one day. This prevents affected HR users from being blocked when recording short unemployment periods around public holiday handling.
Original PR description
Steps: - Create a 'temporary economic employment for employee' timeoff type for an employee for 1 day only - Attempt validating the leave type Cause: Due to the splitting of economic unemployment period by public holidays, economic unemployment durations for 1 day durations are not returned from the splitting method correctly Solution: Returned economic unemployments with durations <= 1 correctly Task: 6511201
This fixes an issue where planning slots with multiple assigned resources could show incorrect allocated hours after resources were added or removed. Working time is now calculated per resource, helping schedules and capacity figures remain accurate for field service planning.
Original PR description
## Steps to reproduce: - Install planning_field_service - Create a planning slot with one resource - Add another resource for the slot we created - Notice the allocated_hours now equals 16h - Remove one of the resources - Notice now the allocated hours are 5h instead of 8h ## Cause: When adding a second resource in a slot and while computing the break_time we use the working hours of all of the resources combined instead of dividing by the number of resources and this messes up the break_time calculation which affects the allocated_percentage and at the end when trying to compute the allocated hours it will be wrongly calculated ## Fix: We divide the working hours by the number of resources to be able to compute the break_time correctly. opw-6307906 Forward-Port-Of: odoo/enterprise#129439 Forward-Port-Of: odoo/enterprise#125641
This fixes an internal HR Appraisal test that could fail when it ran across midnight. The change helps keep automated checks stable so future updates can be validated reliably without false failures.
Original PR description
### Explanation When `test_hr_appraisal` is run at, for example, 23:59:59, the line `self.hr_employee2.next_appraisal_date = date.today()` is executed after midnight, on the following day. As a result, a validation error is raised: `odoo.exceptions.ValidationError: You cannot set 'Next Appraisal Date' in the past.` Forward-Port-Of: odoo/enterprise#127699
Submitting a tax report opened from a return now reliably updates the same return shown on screen. This prevents Dutch VAT corrections from being accidentally submitted or marked against the original VAT return for the same period.
Original PR description
Opening a tax report from a return and submitting it could act on a different return than the one on screen. _get_return_from_report_options searches by company, period and report with limit=1, but…
Opening a tax report from a return and submitting it could act on a different return than the one on screen. _get_return_from_report_options searches by company, period and report with limit=1, but that combination is not unique: l10n_nl declares two return types on l10n_nl.tax_report, nl_tax_return_type and nl_tax_correction_return_type, so a VAT return and its correction both match. Which one is returned is then decided by _order (is_completed, date_deadline, name, id). For a Dutch VAT correction it resolves to the original VAT return of the same quarter, so send_xbrl submits and flags that record instead of the correction. The options already carry the return type they were built for, in the return_periodicity filter, so restrict the search to it when it is set. l10n_nl_reports kept a return_id option for the same reason when computing the already declared amount of a suppletie; it can use _get_return_from_report_options now. opw-6421300 Forward-Port-Of: odoo/enterprise#129278 Forward-Port-Of: odoo/enterprise#127073
This fix ensures Sendcloud shipping labels are returned in the format requested, such as ZPL or PDF. It prevents partner information sent with the request from accidentally replacing the label format setting, avoiding incorrect PDF-only label downloads.
Original PR description
We send the label type we want to get (zpl, pdf, ...) in the request headers. However, since odoo/enterprise#115999, we also send the partner ID in the headers. This was overriding the headers passed to the method, making Sendcloud always return a PDF label. Forward-Port-Of: odoo/enterprise#129542
Delivery charge lines are no longer shown in the Invoiced not Delivered report because they are not physical items that need delivery. This prevents accounting teams from seeing misleading outstanding delivery entries and improves the accuracy of revenue review reports.
Original PR description
Issue: --- Delivery lines are included in `invoiced not delivered` report, which is wrong as delivery lines are not deliverable. Steps: 1- Create a SO with a good product and add a delivery line. Set the product line as delivered and create an invoice. 2- Open accounting, and from review tab, open `Invoiced not Delivered`. As you see, delivery lines are included in the report. Fix: --- On stable we could fix it inside `_get_accrual_domain` by checking if `delivery` is installed. On master we need to implement a solution to be able to differentiate the lines that won't be delivered. opw-6360894 Forward-Port-Of: odoo/enterprise#123517
The signing process now creates completed documents at the right moment and avoids showing duplicate attachments on related records. Users get clearer completion messages and can find signed files reliably in the attachment tray.
Original PR description
This commit refactors the document completion flow to enforce the SRP and resolve duplicate attachments on reference records. Changes include: - Moved PDF generation (`_generate_completed_documents`) from the send method directly into `_sign` to guarantee documents are built exactly when the state changes to 'signed'. - Extracted reference record updates into a dedicated `_update_reference_document` method for cleaner code structure. - Resolved duplicate attachment displays on the source record by explicitly creating the attachment once and removing the redundant `attachment_ids` from the chatter message. - Updated the completion chatter message to notify users that the files are in the attachment tray, and set the message author to the original request creator. - Overrode `_generate_done_message` to cleanly bypass generic activity messages. Task: 6127862
Copying an image that is already attached to another record now reuses the existing file instead of leaving an unnecessary duplicate. This helps keep stored media cleaner and avoids redundant attachment clutter for users editing website or HTML content.
Original PR description
Copying an image attachment already linked to another record could leave a redundant duplicate behind instead of reusing the existing one. opw-6463012 Forward-Port-Of: odoo/odoo#284610 Forward-Port-Of: odoo/odoo#282287
Invoice and journal entry numbering now checks for missing numbers within each suffix-based sequence separately. This prevents valid entries from being incorrectly highlighted as gaps, improving confidence in accounting sequence checks.
Original PR description
### Issue: When moves share the same `sequence_number` in a journal but have different suffixes (e.g. `INV/2026/00010` and `INV/2026/00010A`), the `made_sequence_gap` flag was incorrectly set ###…
### Issue: When moves share the same `sequence_number` in a journal but have different suffixes (e.g. `INV/2026/00010` and `INV/2026/00010A`), the `made_sequence_gap` flag was incorrectly set ### Cause: `_update_sequence_made_gap`, introduced in commit https://github.com/odoo/odoo/commit/17893089e8b21c0ecab5e61ed8e2c33f3731b3ac selects the previous and next moves ordered by `sequence_number` without filtering by suffix This causes two issues: - Moves from different suffix sequences are used as neighbors, leading to incorrect gap detection - Duplicate `sequence_number` values across suffixes are not accounted for, so only one move is considered per number ### Steps to reproduce: - Install `account` - Post 12 invoices to get a sequence up to `INV/2026/00012` - Reset `INV/2026/00012` to draft, rename it to `INV/2026/00010A` - Reset `INV/2026/00010A` to draft, rename it to `INV/2026/00009A` and confirm Before the fix: `INV/2026/00011` is red Expected: `INV/2026/00011` should not be red because `INV/2026/00010` exists - Delete `INV/2026/00009` Before the fix: `INV/2026/00010` is red Expected: `INV/2026/00010` should be red (gap in no-suffix sequence) - Reset `INV/2026/00009A` to draft and confirm it again Before the fix: `INV/2026/00010` is not red Expected: `INV/2026/00010` should still be red (different suffix) ### Notes: Suffix changes are treated as distinct sequences following the same gap rules as any other sequence This was agreed with R&D — the gap flag is meant to signal inconsistencies within a sequence, not across suffixes opw-6454823 Forward-Port-Of: odoo/odoo#282503
This update fixes incorrect and unclear naming for Japanese fiscal positions. It corrects a wrong Japanese translation for domestic partners, fixes an English spelling issue, and removes unnecessary wording so users see clearer accounting labels.
Original PR description
Japanese translation "海外取引先" for domestic was clearly wrong.
Also fixed the misspelling ("Oversea" -> "Overseas") and removed the unnecessary "Customer" context from the name.
@qrtl
---
I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
Forward-Port-Of: odoo/odoo#284608Odoo now saves the updated Microsoft refresh token whenever calendar access is renewed. This prevents users from being unexpectedly asked to reconnect their Microsoft Calendar after the old token expires, reducing disruption for calendar synchronization.
Original PR description
Microsoft issues a new refresh token on every access token refresh (rolling 90-day sliding window). The previous code discarded it, causing users to be forced to re-authenticate every 90 days once the original token expired. Closes #253543 Forward-Port-Of: odoo/odoo#280535 Forward-Port-Of: odoo/odoo#268284
This fix ensures costs are correctly linked to the right sales order when projects share the same analytic account or when a cost line uses multiple analytic accounts. Businesses get more reliable reinvoicing, reducing missed billable costs and manual corrections.
Original PR description
### Before this fix --- The `_get_so_mapping_from_project()` method returns a mapping where the key is the move line ID and the value is a `sale.order` record (or `None`). Because of the issues…
### Before this fix
---
The `_get_so_mapping_from_project()` method returns a mapping where the key is
the move line ID and the value is a `sale.order` record (or `None`).
Because of the issues described below, a valid `sale.order` could be available
for reinvoicing, but the corresponding move line might still not be mapped to
that sale order. As a result, the move line is not added to the reinvoiceable
sale order.
However, the implementation has two issues:
#### 1. Projects are overwritten when they share the same analytic account
`project_per_accounts` is built as a dictionary mapping an analytic account ID
to a single project. If multiple projects reference the same analytic account,
each new assignment replaces the previous one. As a result, only the last
project associated with a given analytic account is retained.
**Example:**
* Analytic Account **AA1** is linked to **Project A** and **Project B**.
* The dictionary becomes `{AA1: Project B}`.
* **Project A** is lost, even though it also references **AA1**.
**Steps to reproduce:**
1. Create an analytic account **AA1**.
2. Create **Project A** and **Project B**, both linked to **AA1**.
3. Create **Sale Order SO1** linked only to **Project A**.
4. Create a vendor bill (or expense) that generates an AML using **AA1** for a
product configured with **Reinvoice Costs = At Sales Price**.
5. Validate the document.
**Expected behavior:**
The product should be added to **SO1** for reinvoicing.
**Actual behavior:**
The move line is not mapped to **SO1**, so no sale order line is created.
#### 2. Previously found projects are overwritten during iteration
The `project` variable is reassigned on every iteration of the loop. After the
loop completes, it only contains the project (or lack of one) corresponding to
the last processed analytic account. This can cause valid projects found earlier
in the loop to be discarded.
**Example:**
* Move line has analytic accounts **AA1** and **AA2**.
* **AA1** maps to **Project A**.
* **AA2** has no linked project.
* After the loop, `project` is `None`, even though **Project A** was found.
**Steps to reproduce:**
1. Create analytic accounts **AA1** and **AA2**.
2. Create **Project A** linked to **AA1** only.
3. Create **Sale Order SO1** linked to **Project A**.
4. Create a vendor bill (or expense) whose AML is distributed between **AA1**
and **AA2**, where **AA2** is processed after **AA1**.
5. Validate the document.
**Expected behavior:**
The move line should still be mapped to **SO1** because **AA1** references
**Project A**.
**Actual behavior:**
The last processed analytic account (**AA2**) overwrites the previously found
project, causing the move line not to be linked to **SO1**.
### After this fix
---
* `project_per_accounts` stores **all** projects associated with each analytic
account instead of keeping only the last one.
* The project lookup preserves all valid project candidates instead of
overwriting previously found results during iteration.
* As a result, the method can resolve the related `sale.order` in more cases,
improving the overall accuracy of the mapping.
> **Note:** This change prevents valid project associations from being lost
> when multiple projects share an analytic account or when multiple analytic
> accounts are processed for the same move line.
**OPW:** 6294615
Forward-Port-Of: odoo/odoo#277110The PDP registration wizard no longer shows a redundant “Production” mention when the system is already in production mode. This avoids confusing users during registration and makes the displayed information clearer.
Original PR description
It makes no sense to mention (Production) on pdp registration wizard when you are in prod mode Forward-Port-Of: odoo/odoo#280501 Forward-Port-Of: odoo/odoo#280360
This fix prevents the barcode manufacturing scrap process from losing the quantity entered during automated checks. It helps ensure scrap operations are validated with the intended positive quantity instead of being incorrectly rejected as zero.
Original PR description
Selecting the product in the scrap form triggers a `stock.move` onchange. The quantity step only waited for the input to exist, not for that onchange to be applied, so the value could be written while it was still in flight and be reset to 0 by its response. It was also assigned directly on the input, without any event, so the field was never flagged as dirty. The scrap was then recorded with a quantity of 0 and `action_scrap` rejected it with "You can only enter positive quantities.". Wait for the quantity input to hold its post-onchange value before typing, and dispatch an input event, like the other scrap tours already do. error-238911 Forward-Port-Of: odoo/enterprise#129410 Forward-Port-Of: odoo/enterprise#128931
Appointment invitation emails now generate public calendar links without permission errors. This ensures invitees receive usable links and reduces failed email rendering during appointment scheduling.
Original PR description
Since calendar attendee access tokens are restricted to system users, appointment mail templates must sudo token reads when generating public calendar links. This follows the same pattern as the calendar mail templates and avoids an AccessError when rendering attendee invitation emails. ref: https://github.com/odoo/enterprise/commit/88a3cca752a5f726cd0260b485fc93f65a268cf8 Task-4711415 Forward-Port-Of: odoo/enterprise#129511
Fixed an issue where invoices created from Point of Sale orders in Chile were not automatically sent to the SII tax authority. This ensures business customers receive compliant invoice processing after checkout without manual follow-up.
Original PR description
Issue: Invoices from PoS orders are not automatically send to SII. Steps to reproduce: - Open PoS - create an order - add a company as customer - pay - close register - go to invoice Current behavior: Invoice is created but not sent Expected behavior: Invoice is created and send to SII. Cause: Before 19.2 invoices were sent using a cron. Starting from 19.2, invoices are sent using the Send button of the invoice form. In order to get a perf improvement, PDF generation was deactivated for l10n_cl PoS invoices at creation. However, the same method used to generate the PDF is used to send the invoice to SII. Therefore, invoices from PoS were not sent to SII. opw-6423528 Forward-Port-Of: odoo/enterprise#126623
Unreconciling one bank statement line from an invoice or bill now only removes that specific match instead of clearing all related reconciliations. This prevents accidental loss of payment matching when multiple bank statements are tied to the same document.
Original PR description
**STEP TO REPRODUCE** 1. Create a bill or an invoice. 2. Create multiples bank statement. 3. Reconciles those bank statements to the invoice/bill. 4. Unreconciles one of those bank statement on the invoice/bill. 5. Notice the invoice/bill is completely unreconciled. Expected behavior: only the unreconciled line should be unreconciled. **CAUSE** When unreconciling a partial linked to a bank statement, we call `delete_reconciled_line()` on both `partial.credit_move_id` and `partial.debit_move_id`. One on those is the the payment_term line of the invoice/bill the bank statement line is reconciled with. This payment_term line is also linked to all partial reconcilliation line on the invoice/bill, so calling `delete_renconciled_line()` delete all the reconciled line of the invoice/bill. **FIX** We should call `delete_renconciled_line()` only on the bank statement move line, not on the payment term line. opw-6465096 Forward-Port-Of: odoo/enterprise#128126
The Studio search view has been updated to match the newer interface used elsewhere. This provides a more consistent experience for users configuring and customizing views in Odoo Studio.
Original PR description
Before this commit, the search view in studio was still the old one After this commit, the search view in studio is like the new one
This fixes an issue where turning a block of content into a list could create an invalid structure and make the list behave incorrectly. Users editing website content can now convert block elements into lists more reliably.
Original PR description
Before this commit, create a list from a div put the div inside of the list element and then doesn't work the proper way After this commit, when creating a list from a div (block element) the a inline element is put inside the list instead. 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
Opening an action that cannot be edited in Studio from the command palette no longer causes a crash. Instead, users see a clear error notification, reducing disruption and making the limitation easier to understand.
Original PR description
Before this commit: 1. Open studio on Home Page 2. Open an action that cannot be editable with studio through command palette 3. Traceback occurs After this commit, the NotEditableActionError is catch and show an error notification.
The Sign app's guided tour was updated so its drag-and-drop step works correctly with the newer tour system. This helps keep automated checks reliable and reduces the risk of unnoticed issues in the signing experience.
Original PR description
Fix the drag_and_drop run of sign_tour to fit in the new tour system.
Swedish ISO20022 batch payments now generate files that correctly match the selected pain.001.001.09 format. This prevents banks from rejecting payment files that were labeled as the newer format but still contained older-format content.
Original PR description
**Steps to reproduce:** - Install Accounting and l10n_se - Switch to a Swedish company (e.g. SE Company) - In Accounting settings, set "Identification" with anything - In Bank journal: * Set an…
**Steps to reproduce:** - Install Accounting and l10n_se - Switch to a Swedish company (e.g. SE Company) - In Accounting settings, set "Identification" with anything - In Bank journal: * Set an account number * Make sure "Swedish ISO20022" is available in "Outgoing Payments" * Set "pain.001.001.09" as "XML Format" in "Outgoing Payments" - Create a vendor payment: * Vendor: [a vendor with a trusted bank account] * Payment Method: Swedish ISO20022 * Amount: [any] - Confirm the payment - From the payments list, select the payment and create a batch - Validate the batch payment **Issue:** When the batch is validated, a `pain.001.001.09` file should be generated. However, its content is that of a `pain.001.001.03` file, even if the version reported in the file is `pain.001.001.09`. For example, `<ReqdExctnDt>` should contains a subnode `<Dt>` in `001.001.09`, which is not the case. It leads to the file being rejected as non-compliant to `pain.001.001.09`. opw-6472050 Forward-Port-Of: odoo/enterprise#129506 Forward-Port-Of: odoo/enterprise#128598
Commit 1. Before this commit, `Record.onChange` binds its two functions to what `this` is at the call site. A record is only reachable as its proxy once the constructor is over, so a registration has to wait for `static new`, where `super.new` has returned it, and both models that register one override `static new` for nothing else. This commit resolves the proxy when the functions run rather than when they are registered, so `setup` can register an onChange, and moves both models to it. Commit 2. Before this commit, a value computed from a record can only be a field with a `compute`, and the model guesses whether that value needs storing: `fieldsComputable` picks the lazy plain-valued fields with eight conditions and a regular expression run on the compute's source. This commit adds `fields.computed()`, so the declaration answers instead of the model: the value is computed on the first read and kept in an owl computed of its own, which the model neither stores nor serializes. The 36 fields the detection was picking are declared instead, so `fieldsComputable` lists what the declarations name and the guessing goes. A `compute` left on a field is scheduled and stored. A computed has no `onUpdate`, so the two fields that had one register an `onChange` from `setup`. This also converts four getters that rebuild a collection on every read, so each one runs on a change instead of on every read. This also fixes what the conversion turned up: - `extra_body_attachment_ids` is declared as an `Attr` whose target model lands as its default value, where the compute returns records: the field becomes a `Many`. - three writes to `is_pinned` in `discuss.channel` never reach the member, as its compute owns the value: opening a channel, opening its chat window and undoing an unpin now set `unpin_dt`, what the compute reads and what the server writes to pin. `updateAttr` warns on such a write instead of dropping it in silence. - `crm.lead` has no `models` declaration and no `@crm` path alias, so the `@this` of its compute names the raw class and the computed value stays untyped. The enterprise counterpart declares `helpdesk.ticket` the same way. Commit 3. Before this commit, a value that goes stale on its own is kept by `Record.computedUntilStale`, a per-record store of its own next to the one `fields.computed` uses. The problem is that the same value needs a key repeating its name, a getter to read it through, and a second place to look for a record's computeds. This commit takes the delay as a third argument of `fields.computed`, so the two clock values of the store are declared like any other computed, and `staleComputeds` goes.
This update reorganizes how helpdesk live chat ticket links and display names are calculated behind the scenes. It improves consistency with the broader messaging system and helps keep the related code easier to maintain without changing the user experience.
Original PR description
Counterpart of "[REF] mail, *: declare a computed on a record", which explains the why. `href` is computed from the record, and nothing stores it.
Spreadsheet documents are now stored and identified using the standard JSON format instead of a custom spreadsheet file type. This makes the file handling more accurate and consistent while keeping the spreadsheet experience unchanged for users.
Original PR description
This commit removes the application/o-spreadsheet mimetype in favor of application/json for spreadsheet documents. New mimetype is more correct as spreadsheets are stored as JSON data. Task: 5416850
This update modernizes internal record observation code by replacing a deprecated mechanism with the newer framework approach. It helps keep the platform easier to maintain and ready for future framework changes, with no expected direct change for end users.
Original PR description
- enterprise: https://github.com/odoo/enterprise/pull/127637 See commit messages for details. --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The mail module now separates the creation of completed activity messages from the rest of the activity completion process. This makes it easier for customizations to change or skip the standard 'Activity Done' message without affecting permissions, attachments, or archiving.
Original PR description
The `_action_done` method in `mail.activity` currently handles multiple responsibilities simultaneously, including permissions, attachments, message posting, and archiving. This commit extracts the chatter message generation logic into a dedicated `_generate_done_message` method. This allows inheriting models to easily override, customize, or completely bypass the generic 'Activity Done' message without duplicating or interfering with the core completion and archiving logic. Task: 6127862 Description of the issue/feature this PR addresses: Current behavior before PR: Desired behavior after PR is merged: --- I confirm I have signed the CLA and read the PR guidelines at www.odoo.com/submit-pr
The Point of Sale app’s internal data and ticket printing services were reorganized into a plugin-based structure. This should make the system easier to maintain and extend across related POS features without changing the day-to-day cashier experience.
Original PR description
Convert the following services to plugins: - pos_data_service - pos_ticket_printer_service
This update reorganizes some point of sale printing and data handling components into a newer plugin structure. It should make future maintenance and country-specific extensions easier without changing day-to-day user workflows.
Original PR description
Convert the following services to plugins: - pos_ticket_printer_service - pos_data_service
This change speeds up manufacturing-related bill of materials checks, especially when confirming large purchase orders with many lines. Businesses using manufacturing, purchasing, sales, point of sale, repairs, or subcontracting should see less slowdown when Odoo needs to evaluate potential kits or components.
Original PR description
Confirming a purchase order of 1000 lines - with only stock & purchase : time is 6.3secs - by adding mrp : time grows to 8.1secs Part of the difference comes from the time it takes to explode the…
Confirming a purchase order of 1000 lines - with only stock & purchase : time is 6.3secs - by adding mrp : time grows to 8.1secs Part of the difference comes from the time it takes to explode the (potential) kits. The refactor of _bom_find consists of: - signature change : company_id -> company_ids to allow searching within multiple companies in one go - return value change : the returned dict's key is now a tuple ( product, company_id or False) Calling _bom_find with no company given : retrieve result with ( product, False) Calling _bom_find with one or more company_id's : retrieve result with ( product, company) -> for _bom_find on record sets having the fields product_id & company_id With this, use case time falls to 6.9secs This will obviously have performance impact on many use cases. 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