| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 7434 |
| Technical Name |
soft_delete_recovery |
| License | LGPL-3 |
| Website | https://github.com |
| Versions | 16.0 |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 7434 |
| Technical Name |
soft_delete_recovery |
| License | LGPL-3 |
| Website | https://github.com |
| Versions | 16.0 |
Soft Delete Manager
Reversible deletes for any Odoo model — with cascade, snapshot backup, full audit trail, and analytics.
Nothing is ever truly lost. Restore even after permanent delete.
| 5 Default Model Cap | 6 Audit Action Types | 3 Severity Levels | 2 Daily Cron Jobs |
Overview
Soft Delete Manager turns Odoo's destructive delete into a reversible Recycle Bin for any model you choose. When a user deletes a protected record, the row is hidden — not removed — and every action is written to an immutable audit log with severity, batch ID, and a JSON snapshot of the data. Children of a deleted parent follow it through a cascade, and even after a permanent delete the record can be recreated from its snapshot, with all its inbound relations reapplied.
A per-user, per-model permission matrix controls who can soft-delete, restore, or hard-delete each protected model. An analytics dashboard surfaces deletion-rate trends, severity breakdowns, time-of-day heatmaps, user activity scores, and model risk rankings. Two daily cron jobs keep the database tidy: one purges expired soft-deletes, the other rotates old audit logs.
Video Demo
Watch Soft Delete Manager in action — full walkthrough of cascade soft delete, snapshot recovery, audit trail, and dashboard analytics.
Why Choose Soft Delete Manager?
|
♻
Reversible Deletes
Records are hidden, not destroyed. Undo a delete in one click.
|
🔒
Per-User Permissions
Three independent toggles for every (user, model) pair. Deny by default.
|
📊
Analytics Dashboard
KPI deltas, severity donut, sparklines, time heatmap, user activity scores.
|
|
📂
JSON Snapshot Backup
Every permanent delete saves a full record snapshot — recreate later from the audit log.
|
🔗
Cascade Aware
Children follow parent on delete and on restore. Linked by batch UUID.
|
⏱
Auto-Cleanup Cron
Configurable TTL for soft-deletes and audit logs — the table never bloats.
|
Key Features
Soft Delete Mixin
Protected models get an x_is_deleted flag; unlink() sets it instead of removing the row.
|
Recover Deleted Button One-click access to the Recycle Bin from list and kanban view headers. |
| Reason Wizard Capture why a record was deleted before it leaves the active dataset. | Cascade Soft Delete Inbound foreign-key children are soft-deleted with the parent, linked by batch UUID. |
| Cascade Restore Restoring a parent automatically restores its tree of cascaded children. | JSON Snapshot Backup Every permanent delete writes a full record snapshot to the audit log first. |
| Restore from Snapshot Recreate a permanently deleted record — with its M2M and inbound relations — from the audit row. | 6-Type Audit Trail soft_delete, cascade_soft_delete, restore, cascade_restore, permanent_delete, auto_cleanup — with severity Info / Warning / Critical. |
| Analytics Dashboard KPI deltas, deletion-rate trend, severity donut, top deleters, time heatmap, model risk. | Per-User Permission Matrix Three toggles per (user, model): Soft Delete, Restore, Permanent Delete. Deny by default. |
| Auto-Cleanup & Retention Two daily cron jobs: TTL on soft-deleted records and TTL on audit log entries. | Email Alerts & XLSX Export Severity-coloured email on every permanent or bulk delete. Filtered audit logs export to Excel. |
How It Works
|
1
|
Configure Protected Models
Pick the Odoo models you want to protect (up to 5 by default, raise the cap up to 100). The mixin is injected and an x_is_deleted flag is added.
|
|
2
|
Delete Triggers Soft Delete
When a user deletes a protected record, the override sets x_is_deleted=True and the row vanishes from list, form, kanban, and graph views via an automatic domain filter.
|
|
3
|
Children Cascade with the Parent Inbound FK children are soft-deleted alongside the parent, all linked by a single batch UUID and a parent-log pointer for traceable trees. |
|
4
|
Every Action is Audited User, company, model, record, IP, user-agent, reason, batch ID, severity — written to an immutable, read-only audit log. |
|
5
|
Recover from the Recycle Bin
Open the Recycle Bin tree filtered to x_is_deleted=True. Click Restore to bring back, or Permanently Delete — both gated by per-user permissions.
|
|
6
|
Recreate from Snapshot, Even After a Permanent Delete Permanent deletes save a JSON snapshot first. Open the audit row and click Recreate Record from Backup — the record and its cascade tree return with relations reapplied. |
How Every Feature Works
A function-by-function breakdown so you know exactly what the module does before you install it.
1. Soft Delete Engine — the foundation
A single abstract model, soft.delete.mixin, gives every protected model the same reversible-delete behaviour without touching the model's own code.
- The flag: a Boolean
x_is_deletedfield is added to each protected model. - The override: calling
unlink()sets the flag toTrue; the row stays in the database. - The escape hatch: passing
_force_unlink=Truein the call context performs a real DB delete — used by Permanent Delete and the auto-cleanup cron. - The filter: every list, form, kanban, and graph action is rewritten with
[('x_is_deleted','=',False)], so soft-deleted rows disappear automatically. - The Recycle Bin: a parallel tree filtered to
x_is_deleted=Trueexposes the hidden rows for review and recovery.
2. Cascade Soft Delete & Restore
A parent never leaves its children behind. Cascading is unconditional and symmetric — the same tree comes back when the parent is restored.
- On delete: every row that holds an inbound foreign key to the parent is soft-deleted with action type
cascade_soft_delete. - Batch ID: all entries from one operation share a UUID stored on each audit row, so the whole tree is queryable in one filter.
- Parent pointer: each child log carries
parent_log_id→ the parent's audit row, exposed under the Related Entries tab. - On restore: the same children are restored with action type
cascade_restore, preserving the batch ID and parent link.
3. Permanent Delete with JSON Snapshot
Even permanent isn't permanent. Before any row leaves the database, the module writes everything needed to recreate it.
- Step 1 — serialize: every stored field of the record is dumped into
record_data_snapshot(a JSON Text field on the audit row). - Step 2 — relation walk: every inbound Many2one and Many2many referrer is recorded in a relations snapshot for later replay.
- Step 3 — hard unlink: the row is removed with
_force_unlink=True; the audit row is the only thing left. - Severity Critical: the audit entry is auto-flagged Critical so it stands out in dashboards and emails.
4. Restore from Snapshot — recovery after permanent delete
Open any audit row whose snapshot is present and click Recreate Record from Backup.
- Recreate the parent:
action_restore_from_snapshotrebuilds the original record from its JSON. - Recreate the tree: the cascade is followed via
parent_log_idto recreate every child. - ID remapping: the new IDs assigned by Odoo are remapped across the tree so foreign keys point to the right rows.
- Reapply relations:
_sd_reapply_relationsrebuilds Many2many links and inbound M2O / M2M references that pointed to the old record.
5. Audit Trail (soft.delete.audit.log)
Every lifecycle event is recorded with full context. The log is read-only from the UI; only SUPERUSER can intervene.
| Action | Severity | When it fires |
|---|---|---|
soft_delete |
Info | A user soft-deletes a protected record. |
cascade_soft_delete |
Warning | Children follow a parent soft delete. |
restore |
Info | A user restores a soft-deleted record. |
cascade_restore |
Info | Children follow a parent restore. |
permanent_delete |
Critical | A user hard-deletes from the Recycle Bin. |
auto_cleanup |
Critical | The cron permanently deletes an expired soft-deleted row. |
- What's captured: user, company, model + record name, IP, user-agent, deletion reason, batch ID, parent log link, severity, timestamp, full record snapshot.
- Tree view: colour-coded per severity (red / yellow / green / blue) and read-only — no edits or deletes from the UI.
- Search: filter by user, model, action, batch, severity, or date range.
- Export: one-click Export to XLSX with severity-coloured rows (
export_audit_logs_xlsx). - Manual alert: Send Email Alert button on the audit form to notify after the fact.
6. Analytics Dashboard (soft.delete.dashboard)
A standalone dashboard built on aggregate audit data. Toggle off with enable_dashboard=False if you don't need it.
- KPI cards with deltas: totals for the current window vs. the previous equal-length window, with % change.
- Deletion-rate trend: daily counts across all configured models with a 7-day moving average (window length configurable).
- Top deleters leaderboard: users ranked by deletion count.
- Severity breakdown donut: Info / Warning / Critical share of audit volume.
- Per-model sparklines: 14-day micro-trends per protected model.
- Fastest-growing model: alert highlighting the model with the largest positive delta.
- Time pattern heatmap: hour-of-day × day-of-week deletion density.
- User activity scores: risk score per user, weighted by severity (Info×1, Warning×2, Critical×5; weights configurable).
- Model risk analysis: models ranked on
total_deletes + permanent_deletes×3. - Recent deletions stream: latest soft-deletes across every model in one feed.
7. Per-User Permission Matrix (soft.delete.user.permission)
Three independent toggles per (user, model) pair. Permissions are explicit — no row, no access.
- Can Soft Delete — send a record to the Recycle Bin.
- Can Restore — bring a record back from the Recycle Bin.
- Can Permanently Delete — hard-delete a record from the Recycle Bin (high-risk; off by default).
- Deny by default: a user with no permission row for a model gets nothing. Even System Administrators are gated; only the SUPERUSER (uid 1) bypasses.
- Bulk helpers on the user form: Add All Protected Models populates rows with safe defaults (soft=on, restore=off, permanent=off); Clear All wipes them.
- Two-layer enforcement:
- Server-side gate
_sd_can(action, model_name)— final authority, raisesAccessErroron deny. - Front-end RPC
sd_get_button_perms(model_name)— pre-hides buttons in list, kanban, and form views; cached for 10 seconds.
- Server-side gate
- Row decorations: green when all three are checked, yellow when soft+restore only, red when none.
8. Email Notifications
Severity-coloured HTML alerts driven by the soft_delete_audit_notification_template.
- Header bar coloured by severity: red (Critical), yellow (Warning), green (Info).
- Body fields: action, user, model, record + display name, record count, date, IP, deletion reason, details, batch ID, snapshot availability.
- Per-event trigger: every permanent delete (toggle
notify_on_permanent_delete). - Threshold trigger: when a single batch exceeds
bulk_delete_threshold(default 10). - Recipient list: configurable per
soft.delete.managerecord vianotification_user_ids.
9. Schedulers (Cron Jobs)
Two daily, unlimited-recurrence cron jobs in data/soft_delete_cron.xml:
- Soft Delete: Auto-Cleanup Expired Records —
_cron_auto_cleanup. Permanently deletes rows whosex_is_deleted=Trueis older thanauto_cleanup_days. Default is 0 (disabled). Each row removed gets anauto_cleanupaudit entry with a snapshot first. - Soft Delete: Cleanup Old Audit Logs —
cleanup_old_logs. Removes audit rows older thanaudit_log_retention_days(default 90) so the log table never bloats.
10. Reason Wizard (soft.delete.reason.wizard)
A transient pop-up that captures the why before a record leaves the active dataset. Triggered from the form view's Delete with Reason action-menu item.
- Three fields:
reason(required Text),res_model(target model),res_ids(JSON list of IDs — supports batch). - Confirm path:
action_confirmparses the JSON IDs, callsunlink()with the reason planted inself.env.context['soft_delete_reason'], then closes itself. - Audit pick-up: the mixin reads the reason from the context and stores it on the audit row's
deletion_reasonfield, surfacing it in the email template and dashboard. - Permission gated: the menu item only appears if the user has
can_soft_deletefor that model.
11. Recycle Bin & "All Modules" Live View
Two complementary ways to find soft-deleted rows — one per model, one across every protected model in a single grid.
- Per-model: the Recover Deleted button on any list or kanban view opens a transient wizard listing the deleted rows for that model. The wizard is created dynamically when the model is first protected, so every protected model gets its own tailor-made Recycle Bin.
- Cross-model: the All Modules menu (
soft.delete.manager.all.modules) renders a SQL view enumerating every dynamically-created wizard model with a live deleted-record count. The view is dropped and recreated on every search so the numbers are always fresh, never cached. - Reverse name mapping: wizard names like
x_partner_custom_wizardare mapped back to source model names likepartner.customvia_get_source_model_name— clicking a row in All Modules opens the matching Recycle Bin tree. - Empty-safe SQL: when no wizard tables exist yet (fresh install), the underlying UNION ALL falls back to a no-op
WHERE FALSEstub instead of erroring.
12. Custom Tracking Fields (the x_* set)
When a model is added to soft.delete.manage.model_ids, eight fields are auto-injected via _ensure_soft_delete_fields. All are stored, readonly to users, marked state='manual', and have copied=False so they never leak into duplicates.
| Field | Type | What it stores |
|---|---|---|
x_is_deleted |
Boolean | The soft-delete flag (the rest of the system reads this). |
x_deleted_by |
Many2one → res.users | The user who triggered the soft delete. |
x_deleted_date |
Datetime | When the soft delete fired. |
x_deletion_reason |
Text | Reason captured by the Reason Wizard, if any. |
x_cascade_deleted_from |
Char | Breadcrumb "parent_model,parent_id" for rows that were soft-deleted by cascade. |
x_restored_by |
Many2one → res.users | The user who restored the row (if it was restored). |
x_restored_date |
Datetime | When the restore happened. |
x_relations_snapshot |
Text (JSON) | Inbound M2O / M2M references cleared on cascade delete — replayed by _sd_reapply_relations on restore. |
13. Multi-Company Support
Audit data is correctly attributed to the right company in multi-company databases — even when SUPERUSER is the actor.
- Auto-resolved company:
log_actionfillscompany_idfrom the acting user's company; for SUPERUSER it usesself.env.company.id; failures default toFalserather than raising. - Search filters: the audit-log search view exposes Company as a field, filter, and group-by — all conditional on
base.group_multi_company. - Record-rule friendly: standard Odoo record rules on
res.companyapply automatically; users only see audit rows for companies they're allowed to read. - Email recipients: the
notification_user_idsrecipient list is persoft.delete.managerecord, so each company can configure its own alert routing.
Settings & Configuration
Every tunable lives in Settings → Soft Delete (global) or on the Soft Delete Settings form (per-config). Defaults are sensible — touch them only when you need to.
Limits & Caps
| Key | Default | Purpose |
|---|---|---|
max_models |
5 (max 100) | Maximum protected models per config record. |
top_users_limit |
10 | Top deleters slice on the dashboard. |
top_models_limit |
10 | Model inventory rows on the dashboard. |
recent_entries_limit |
20 | Recent deletions stream length. |
trend_window_days |
30 | Days covered by the deletion-rate trend chart. |
moving_avg_days |
7 | Smoothing window for the moving average overlay. |
user_scores_limit |
15 | Rows in the user activity scores table. |
Severity Score Weights
| Key | Default | Purpose |
|---|---|---|
score_info |
1 | Weight applied to Info-severity actions in user risk scores. |
score_warning |
2 | Weight for Warning-severity actions. |
score_critical |
5 | Weight for Critical-severity actions. |
Privacy & Performance Toggles
| Key | Default | Purpose |
|---|---|---|
enable_ip_tracking |
true | Capture client IP in audit logs. |
enable_user_agent_tracking |
true | Capture browser user-agent in audit logs. |
enable_undo_toast |
true | Show an undo toast immediately after a soft delete. |
enable_xlsx_export |
true | Allow audit log export to Excel. |
enable_dashboard |
true | Master kill-switch for the analytics dashboard (turn off if you don't need it). |
Defaults for New soft.delete.manage Records
| Key | Default | Purpose |
|---|---|---|
default_bulk_delete_threshold |
10 | Default bulk-delete email-alert threshold. |
default_audit_log_retention_days |
90 | Default TTL for audit log rows. |
default_auto_cleanup_days |
0 (disabled) | Default TTL for soft-deleted records (0 disables auto-cleanup). |
Per-Config Toggles (Soft Delete Settings form)
- Email alerts:
notify_on_permanent_delete,notify_on_bulk_delete,bulk_delete_threshold,notification_user_ids. - Retention:
auto_cleanup_days,audit_log_retention_days(override the global defaults per config). - Uninstall preferences: per-model Recover vs Delete choice; bulk Recover All / Permanently Delete All helpers; live summary of expected outcome on uninstall.
Frontend Layer
The browser-side patches that put the soft-delete UI into Odoo's list, kanban, and form controllers — plus the Archive Vault dashboard component and its themes.
Utility Layer (soft_delete_utils.js)
Shared helpers that every view controller calls before deciding which buttons to render.
checkSoftDeleteEnabled(orm, modelName)— callsres.users.sd_is_model_protected()over RPC and remembers the answer for the rest of the session. Fail-closed: if the call errors, the buttons are hidden so we don't advertise a broken feature.getSoftDeletePerms(orm, modelName)— callsres.users.sd_get_button_perms()and caches the three booleans for 10 seconds. Fail-open: if the call errors, the buttons are shown but the server-side gate_sd_canstill blocks the action, so nothing slips through.clearSoftDeleteCache(modelName)andclearSoftDeletePermsCache(modelName)— manual invalidation hooks; pass no argument to wipe the entire cache.- No leading underscores: Odoo's JSON-RPC layer rejects calls to private methods, so every cache helper is deliberately exposed with a public name.
List & Kanban View Buttons
Two patches inject the same UI into both list and kanban controllers (soft_delete_tree_view_header_button.js and soft_delete_kanban_view_header_button.js).
- Recover Deleted button in the view header — only rendered if the model is protected and the current user has
can_restore=True. Click opens the Recycle Bin tree pre-populated for that model. - Delete with Reason entry in the bulk-action dropdown — triggers the Reason Wizard with the selected IDs.
- Undo toast after every soft delete (controlled by
enable_undo_toast). The toast carries an Undo action that callssoft.delete.manage.restore_recordsand reloads the list. Auto-dismisses on navigation. - Display name fetch: on click, the button does a small
ir.model.search_readcall so the wizard window title shows "Recycle Bin: Sales Order" instead of "Recycle Bin: sale.order".
Form View Action Menu (soft_delete_form_view_header_button.js)
Patches FormController to add two action-menu items on protected models.
- Delete with Reason — opens the Reason Wizard for the current record. Visible only when
can_soft_delete=True. - Open Recycle Bin — jumps to the per-model Recycle Bin tree. Visible only when
can_restore=True. - Post-delete redirect: after a successful soft delete, the form redirects to the model's list view since the current record is no longer visible there.
Archive Vault Dashboard Component (soft_delete_dashboard.js / .xml)
An OWL component (SoftDeleteDashboard) that renders every chart and table you see on the Archive Vault page.
- Filter bar: period chips (7 d, 30 d, 90 d, custom), date pickers, model dropdown, user dropdown.
- Auto-refresh: a checkbox in the header toggles a 60-second polling loop. The loop is cleared automatically on component unmount so it never leaks.
- Drill-down: clicking any KPI, severity slice, model bar, user score, or timeline row routes to the audit log tree view with a pre-built domain — one click takes you from "who made the most permanent deletes last week" to the actual rows.
- Export: a Download button calls
export_dashboard_xlsxwith the active filters and streams an Excel file back. - Initial period: derived from the session-info payload (see below) so the chart range matches the global setting on load.
- Disabled state: when
enable_dashboard=false, the server returns{enabled:false}and the component renders a friendly placeholder instead of empty charts.
Session-Info Injection (ir.http override)
A small session_info() override pushes four configuration values into every page-load payload so the JS layer never has to do a synchronous bootstrap call.
enable_undo_toast— read by the list controller before showing the post-delete notification.enable_dashboard— read by the dashboard component to short-circuit data loading when off.enable_xlsx_export— read to hide the Excel-export buttons when off.trend_window_days— sets the dashboard's initial period chip without a round trip.- Fail-safe: the override is wrapped in
try/exceptand falls back to safe defaults so a misconfiguration can never break the session bootstrap.
Themes (SCSS)
Two SCSS files style the dashboard and an opt-in dark "hacker" overlay for individual list/form views.
soft_delete_dashboard.scss— slate + rust-orange professional theme with dual-layer KPI cards, chip-style filters, and a body-class scrollbar fix scoped via.sdr-dashboard-mountedso the override never leaks out of the dashboard.soft_delete_hacker.scss— opt-in phosphor-green-on-near-black overlay activated by addingclass="o_sdr_hacker"to a tree or form arch root. The v10.7.22 selector chain uses bare.o_sdr_hacker, the:has()traversal, and explicit.o_form_renderer.o_sdr_hackertogether so the styles attach no matter where Odoo 16 puts the class. A subtle text-shadow glow is applied via thehk-glowmixin.
Module Lifecycle
What happens on every server start and at uninstall — with safety nets at every step.
Server Start — _register_hook (relation tables)
Runs every time the registry is built. Idempotent — never re-creates what already exists.
- Two M2M relation tables created if missing:
res_config_settings_model_ids_relandres_config_settings_specific_models_recover_rel. - Existence check first:
information_schema.tablesis queried before any DDL; no destructive operations run unconditionally. - UNIQUE INDEX on
(config_id, model_id)for data integrity. - Silent on duplicates: table-already-exists and index-already-exists errors are swallowed so a fresh install and an upgrade behave identically.
Uninstall Wizard (base.module.uninstall override)
When a user clicks Uninstall on the Soft Delete Manager module, the standard Odoo uninstall wizard gets an extra tab where each protected model is listed with a per-model Recover vs Delete choice.
- Pre-populated: the wizard's
default_getreads the saved decisions fromsoft.delete.manage.uninstall_line_ids, so administrators can configure their preferences months ahead. - Live summary: a computed sentence at the top — "Will recover 42 records across 3 models; permanently delete 10 records across 2 models" — updates as the choices change.
- Bulk helpers: one-click Recover All and Permanently Delete All buttons.
- Phantom-row hardening: the transient model's
create/writeoverrides silently drop empty(0, 0, {})commands the web client emits when reconciling the One2many field, so opening the wizard twice never breaks state. - Persistence to ir.config_parameter:
action_uninstallserialises the decisions as JSON into thesoft_delete_recovery.uninstall_preferencesparameter before the parent uninstall runs, because the persistent tables are gone by the time the post-uninstall hook fires.
Uninstall — uninstall_hook
Runs after the records and views have been removed but before the registry forgets the module. Reads the JSON preferences and acts on them.
- Resolve preferences: reads
soft_delete_recovery.uninstall_preferences; falls back to legacy comma-separated id-list parameters if the JSON variant is missing. - SAVEPOINT-isolated per-model action: for every
(model, action)pair the hook opens a SAVEPOINT, runs the action (recover →x_is_deleted=False; delete →unlink_original), and either RELEASEs or ROLLBACKs that savepoint. One model failing does not poison the rest. - Audit-log the cleanup: each row touched gets a
restoreorauto_cleanupentry so the log preserves the trail even after the module is gone. - Final cleanup: the
action_cleanup_soft_deletemethod strips custom views, server actions, and dynamically-created fields; then everysoft_delete_recovery.*parameter is wiped so a future reinstall starts clean.
Models Reference
Every Python model the module ships, organised by layer.
Core layer
| Model | Kind | Role |
|---|---|---|
soft.delete.mixin |
AbstractModel | Adds x_is_deleted and overrides unlink() on every protected model. |
soft.delete.manage |
Model | Central config: protected models, retention, alerts, uninstall preferences. Owns _ensure_soft_delete_fields and action_cleanup_soft_delete. |
soft.delete.audit.log |
Model | Immutable lifecycle log + every analytics method consumed by the dashboard + restore-from-snapshot. |
soft.delete.dashboard |
AbstractModel | Aggregates audit data into the get_dashboard_data payload (KPI deltas, sparklines, severity donut, fastest-growing model). |
soft.delete.user.permission |
Model | Per-user, per-model 3-flag matrix. Unique on (user_id, model_id). |
soft.delete.reason.wizard |
TransientModel | Captures the deletion reason and forwards it to the mixin via context. |
soft.delete.manager.all.modules |
Model (SQL view, _auto=False) |
Live UNION ALL across every wizard table for the cross-model Recycle Bin grid. |
Extensions to standard Odoo models
| Inherits | What's added |
|---|---|
res.users |
Permissions tab on the user form, bulk helpers, the _sd_can server gate, and the public RPCs sd_get_button_perms / sd_is_model_protected. |
res.config.settings |
Every global tunable surfaced earlier in Settings & Configuration. |
ir.http |
session_info() override pushing four feature flags into the page-load payload. |
base.module.uninstall |
Per-model recover/delete decision tab + savepoint-isolated execution path for soft-delete-aware uninstalls. |
Helper / lifecycle
| Model | Role |
|---|---|
soft.delete.manage.uninstall.line |
Persistent per-model recover/delete decision; unique on (manage_id, model_id). |
soft.delete.uninstall.line.wizard |
Transient mirror of the line model with phantom-row filtering for the wizard form. |
execute.soft.delete.rel.tables |
AbstractModel; _register_hook creates the two M2M relation tables idempotently at every server start. |
soft.delete.manager.config (legacy) |
Older configuration model retained for backward compatibility — not the active flow. |
Compatibility
| Odoo 16 Community | Odoo 16 Enterprise | Python 3.8+ |
| PostgreSQL 12+ | OWL 2.0 | Any Odoo Model |
Quick Start
|
1
|
Drop the module into your Odoo addons directory and refresh the Apps list. |
|
2
|
Search for "Soft Delete Manager" and install. |
|
3
|
Open Soft Delete Manager → Soft Delete Settings and pick the models to protect. |
|
4
|
Grant access on the user form's Soft Delete Permissions tab — remember deny by default. |
|
5
|
Tune limits, weights, and toggles in Settings → Soft Delete. Use "Recover Deleted" on any list/kanban to find the Recycle Bin. |
Ready to Get Started?
Reversible deletes, cascade-aware recovery, snapshot backup, and an audit trail you can trust.
|
Support Author: DC Software dcsoftware.support@gmail.com |
License LGPL-3 Version 16.0.10.7.22 | Odoo 16 |
Please log in to comment on this module