| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 1334 |
| Technical Name |
bfs_recycle_bin |
| License | OPL-1 |
| Website | https://www.bexfordsystems.com/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 1334 |
| Technical Name |
bfs_recycle_bin |
| License | OPL-1 |
| Website | https://www.bexfordsystems.com/ |
Recycle Bin
Protect data from accidental deletion. Intercepts deletes, preserves all relational data, and lets you restore in seconds for any Odoo model.
How It Works
Four simple steps from deletion to restoration
User Deletes Record
Standard Odoo delete triggers the Recycle Bin interception layer.
Record Serialised
All fields - simple, Many2one, Many2many, One2many children - captured to JSON.
Bin Entry Created
A recycle.bin.item is created. The original record is removed from the DB.
Restore Anytime
Manager opens Recycle Bin, inspects the record, and restores with one click.
Core Features
Everything you need for enterprise-grade record recovery
Generic - Any Model
Hooks into Odoo's abstract base model. Works on contacts, products, invoices, custom models - without per-model code.
Full Relational Integrity
Captures Many2one, Many2many link tables, and One2many child rows including invoice lines. Warns about missing targets before restore.
One-Click Restore
A guided restore wizard re-establishes all relationships. If a related record is missing, the user can restore without it after confirming.
Odoo Restrictions Respected
Standard @api.ondelete guards are honoured. If a confirmed sale order cannot be deleted, the bin entry is rolled back automatically.
Settings UI
Configure enabled models, retention period (days), and deletion confirmation via the standard Odoo Settings interface. No developer needed.
Auto-Purge Cron
A daily scheduled action permanently purges bin items past their retention date. Set retention to 0 for indefinite storage.
Role-Based Security
Recycle Bin User: read & restore. Recycle Bin Manager: full access including permanent delete.
Delete Confirmation Popup
A JavaScript patch shows a custom confirmation dialog before deletion: "This record will go to the Recycle Bin. You can restore it later."
Accounting Support
Works with account.move with full invoice line capture, account.tax, account.payment.term, account.journal, and more.
Attachment Awareness
Attachments linked to deleted records are detected and re-linked on restore. Duplicate attachment creation is prevented automatically.
Bypass Context
Pass recycle_bin_bypass=True in context to permanently delete without the bin - useful for migrations and cleanup scripts.
Search, Filter & Group By
Full-featured list view with search bar, filters by model and state, grouping, bulk restore and bulk permanent-delete.
Screenshots
See the Recycle Bin in action inside Odoo 18
What's Covered
Full transparency - every scenario documented and tested
Any configured model goes to bin instead of permanent delete.
Many2one, Many2many, and One2many data re-established where targets exist.
Cursor-level stash captures lines before Odoo's MRO deletes them.
Wizard warns about missing targets. User confirms and restores with fields left empty.
Confirmed sale orders, posted invoices - bin entry rolled back cleanly if blocked.
Selecting N records creates N individual bin entries in one operation.
Draft journal entries, taxes, payment terms, journals recycled and restored correctly.
Aliased O2M fields (line_ids / invoice_line_ids) captured once - no duplicate restore.
recycle_bin_bypass=True skips the bin for data migrations and scripts.Children with
ondelete='cascade' at DB level bypass the ORM and are not captured.Binary fields (images, PDFs in fields) excluded to keep bin items lightweight.
Restored records receive a new ID. Original stored in
res_id; new in restored_res_id.mail.message, log notes, and tracking values excluded. Clean chatter on restore.Odoo 18 aborts if you set computed fields in
create(). Odoo recomputes them automatically.Uses
_inherits = {'account.move': 'move_id'}. Recycle the parent statement instead.Wizards (
TransientModel) and abstract models are never intercepted.Accounting Model Support
Which models to enable, and which to leave excluded
Enable These in Settings
| Model Name | Technical Name | Notes | Can Delete? |
|---|---|---|---|
| Journal Entry / Invoice | account.move | Draft only. Invoice lines fully captured via cursor stash. | Draft only |
| Tax | account.tax | Fully recyclable and restorable | Yes |
| Payment Term | account.payment.term | Fully recyclable and restorable | Yes |
| Reconcile Model | account.reconcile.model | Fully recyclable | Yes |
| Journal | account.journal | Recycles journal config; related entries not moved | Yes |
| Payment | account.payment | Draft payments only | Draft only |
Never Configure These (Already Excluded)
| Model Name | Technical Name | Reason |
|---|---|---|
| Journal Line | account.move.line | Cascade child - captured via cursor stash into parent bin entry. Configuring separately causes duplicates. |
| Bank Statement Line | account.bank.statement.line | Uses _inherits = {'account.move': 'move_id'}. Independent recycling causes cascade conflicts. |
| Partial Reconcile | account.partial.reconcile | Technical link record - no standalone business meaning. |
| Full Reconcile | account.full.reconcile | Technical link record - no standalone business meaning. |
Test Results
Comprehensive automated test suite - all passing on Odoo 18
TC-01 Record moved to bin, not permanently deletedPASSTC-02 Unconfigured model - standard permanent deletePASSTC-03 Excluded system models bypass binPASSTC-04 Many2one reference preservedPASSTC-05 Many2many references preservedPASSTC-06 One2many children preserved (generic model)PASSTC-07 Missing Many2one raises UserError on restorePASSTC-08 Missing Many2many - partial restorePASSTC-09 Confirmed sale.order blocked - bin rolled backPASSTC-10 Cron purges expired bin itemsPASSTC-11 Permanent delete marks item statePASSTC-12 Restore twice raises UserErrorPASSTC-13 Bulk delete stores all recordsPASSTC-14 Settings configure enabled modelsPASSTC-15 Bypass context permanently deletesPASSTC-16 Integrity check detects missing relationsPASSTC-A01 account.tax recycled and restoredPASSTC-A02 account.payment.term recycled and restoredPASSTC-A03 account.reconcile.model recycledPASSTC-A04 Draft account.move recycled with invoice linesPASSTC-A05 Posted account.move blocked - bin rolled backPASSTC-A06 account.move.line NOT double-storedPASSTC-A07 account.move restored with journal_id + linesPASSTC-A08 account.journal recycledPASSTC-A09 account.bank.statement recycledPASSTC-A10 Bulk delete of 3 draft moves storedPASSTC-A11 account.move.line in EXCLUDED_MODELSPASSTC-A12 account.bank.statement.line excludedPASSTC-A13 Restored account.move has state draftPASSTC-A14 Missing journal detected by integrity checkPASSInstallation
Up and running in under 5 minutes
Copy module to addons path
Extract the zip and place bfs_recycle_bin/ inside your Odoo addons directory.
Update app list & install
Developer mode Apps Update Apps List search Recycle Bin Install.
Configure models in Settings
Settings Technical Recycle Bin - select models, set retention days, save.
Access the Recycle Bin
Open the top-level Recycle Bin menu. Click Restore to recover any record.
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module