| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
Discuss (mail)
|
| Lines of code | 1878 |
| Technical Name |
auto_archive_rules |
| License | OPL-1 |
| Versions | 16.0 17.0 18.0 19.0 |
Auto Archive Rules
Keep your Odoo database clean automatically — archive, reassign, tag, or notify stale records on any model with a daily cron job and full audit trail.
Stop cleaning your database manually
Define rules once. Every night the cron job scans your chosen model, finds records that have gone stale past your threshold, and automatically takes the action you configured — while keeping a full audit trail so you can undo anything with a single click.
Everything you need, nothing you don't
Any Odoo Model
CRM, Sales, Purchases, Products, Events — or any custom model with an active field.
7 Action Types
Archive, change stage, reassign user, add tag, schedule activity, send email, or run custom Python.
Dry Run Mode
Preview exactly which records would be affected before making any real changes. Always starts enabled on new rules.
One-Click Undo
Every run snapshots the before-state. Click Undo on any log entry to restore records instantly.
Warning Emails
Notify the responsible user N days before a record is acted on. Each record warned only once per rule.
Smart Exceptions
Skip records with open activities, specific tags, or unpaid invoices. Whitelist domains protect records permanently.
Analytics Dashboard
Graph and pivot views track records affected over time by rule and model, with daily digest snapshots.
Slack & Teams Alerts
Post a daily summary to Slack or Microsoft Teams automatically after every cron run via webhook.
Template Library
Pre-built rules for CRM, Sales, Purchase, Inventory, and Events. Activate in one click — starts in Dry Run.
Configure a rule in under a minute
Choose the model, set the inactivity window, pick an action type, and optionally add filter conditions with the visual Condition Builder — no domain syntax required.
- Visual Condition Builder or raw Odoo domain
- Whitelist domain to protect key records always
- Per-rule company scoping for multi-company
- Run Now button with instant count feedback
Every run logged. Every action undoable.
The Run History tab shows every execution with timestamps, affected counts, and action type. Ran a rule too aggressively? Click Undo to restore all records to exactly where they were.
- Before-state snapshot on every real run
- Restores archives, stage changes, tags & more
- Precise — only reverses what this run changed
- One-time per log entry with confirmation prompt
7 ways to act on stale records
| Action | What it does | Undoable |
|---|---|---|
| Archive | Sets active = False on matching records |
✓ |
| Change Stage | Moves records to a target stage or state value | ✓ |
| Assign to User | Writes a new owner to the user_id field |
✓ |
| Add Activity | Creates a follow-up activity on each matching record | ✓ |
| Add Tag | Appends configured tags to a Many2many field | ✓ |
| Send Email | Fires a configured mail template for each record | — |
| Custom Python | Runs arbitrary Python on the full matched recordset | — |
5 ways to measure staleness
write_date — fastestUp and running in 60 seconds
Browse the pre-built library and click Activate on any card to instantly create a ready-to-use rule.
Dry Run is on by default. The notification tells you exactly how many records would be affected.
The nightly cron handles everything from here. Check the Dashboard for trends over time.
Auto Archive Rules
Automatically archive, reassign, tag, or notify stale records on any Odoo model. A daily scheduled job runs all active rules with a full audit trail and one-click undo.
Quick Start
- Go to Auto Archive → Templates and click Activate on any pre-built template.
- The rule opens in form view with Dry Run enabled — click Run Now.
- A notification tells you how many records would be affected.
- Review the Run History tab to confirm the right records were matched.
- Disable Dry Run on the rule form and save.
- The nightly cron handles everything from here.
Creating a Rule
Navigate to Auto Archive → Archive Rules and click New.
Target Settings
- Model
- The Odoo model to scan (e.g. Lead/Opportunity, Sale Order, Product). Any non-transient model with an active field is supported.
- Days of Inactivity
- How many days a record must be inactive before the rule acts on it. Set to 0 to match all records regardless of age.
- Inactivity Type
- How inactivity is measured — see Inactivity Types below.
- Whitelist Domain
- Records matching this domain are always skipped, regardless of inactivity. Example: [('partner_id.customer_rank', '>', 0)]
Status Settings
- Active
- Enable or disable the rule. Inactive rules are skipped by the cron.
- Dry Run
- When enabled the rule logs what would happen but makes no changes. Always start a new rule in Dry Run and disable it only after reviewing the results.
- Company
- Visible only in multi-company installations. Leave empty to run for all companies.
Filter Conditions
Use Condition Builder
Toggle Use Condition Builder for a visual row-by-row editor. All conditions are AND'd together. This is the easiest option if you are not familiar with domain syntax.
Filter Domain
A raw Odoo domain expression to narrow which records are considered. Leave empty to match all active records on the model.
Examples:
[('state', '=', 'draft')]
[('team_id.name', '=', 'Direct Sales')]
[('probability', '<', 20)]
See Domain Expression Reference for a full guide.
Action Types
Archive
Sets active = False on all matching records. This is the default action. No extra configuration required.
Undoable: Yes
Change Stage
Moves matching records to a target stage or state value.
- Stage Field
- The field to update. Default is stage_id. Can also be state or any other field on the model.
- Target Value
- For Many2one fields: the stage name (e.g. Lost). For selection fields: the selection key (e.g. cancel).
Undoable: Yes — each record's previous value is restored.
Assign to User
Writes a new owner to the record's user_id field.
- Assign To
- The user to assign matching records to.
Undoable: Yes — each record's previous user is restored.
Add Activity
Creates a follow-up activity on each matching record. The model must inherit mail.thread.
- Activity Type
- e.g. To-Do, Email, Phone Call.
- Summary
- Activity title shown on the chatter.
- Deadline (days)
- Number of days from today when the activity falls due.
- Assign Activity To
- Leave empty to assign to the record's responsible user (user_id).
Undoable: Yes — activities created by this run are deleted.
Send Email
Fires a mail template for each matching record. The template selector is automatically filtered to the chosen model.
- Email Template
- The mail.template to send.
Undoable: No — emails already sent cannot be recalled.
Add Tag
Appends one or more tags to a Many2many field on matching records. Tags are created automatically if they do not already exist.
- Tag Field
- The Many2many field to write to. Default is tag_ids.
- Tag Names
- Comma-separated tag names, e.g. Stale, Needs Review.
Undoable: Yes — only the tags added by this run are removed. Pre-existing tags on the record are left untouched.
Custom Python
Runs arbitrary Python code on the matched recordset. Restricted to Odoo administrators. Always test with Dry Run first.
Available variables:
| Variable | Description |
|---|---|
| records | Recordset of all matched records |
| env | Odoo environment |
| rule | The current auto.archive.rule record |
| timedelta | datetime.timedelta |
| _logger | Python logger |
Example:
# Set priority to High on all matching leads
records.write({'priority': '2'})
# Post a note on each record's chatter
for rec in records:
rec.message_post(body="Flagged as stale by Auto Archive.")
Undoable: No — arbitrary code changes cannot be automatically reversed.
Inactivity Types
| Type | What it measures | Performance |
|---|---|---|
| Last Update | Standard write_date | Fast — uses DB index |
| Creation Date | create_date — good for records never touched after creation | Fast — uses DB index |
| Last Activity | Most recent mail.activity on the record | Slower — Python scan |
| Last Email Received | Most recent inbound message in the chatter | Slower — Python scan |
| Last Stage Change | Most recent stage_id change via mail tracking | Slower — Python scan |
Exceptions
Skip if Open Activity
Records with at least one pending activity are left alone.
Skip if Tagged
Enter a comma-separated list of tag names. Records carrying any of those tags are skipped.
- Tag Field
- The Many2many field to check. Default is tag_ids.
Skip if Unpaid Invoice
Requires the Accounting app. Records whose partner has at least one posted, unpaid invoice are skipped.
Whitelist Domain
Records matching this domain are always skipped regardless of inactivity or other settings. Evaluated before any exception checks.
One-Click Restore (Undo)
Every real run (non-dry-run) captures a snapshot of the records before the action is applied. You can restore them at any time from the Run History tab on the rule form.
To undo a run:
- Open the rule in Auto Archive → Archive Rules.
- Click the Run History tab.
- Find the run you want to reverse and click Undo.
- Confirm the prompt.
The Restored column is ticked after a successful undo. Each log entry can only be undone once. Records that were deleted after the run are silently skipped during restore.
| Action | What is restored |
|---|---|
| Archive | Records are unarchived (active = True) |
| Change Stage | Each record's field is set back to its previous value |
| Assign to User | Each record's user_id is set back to the previous owner |
| Add Activity | Activities created by the run are deleted |
| Add Tag | Only the tags newly added by the run are removed |
| Send Email | Not restorable |
| Custom Python | Not restorable |
Pre-Archive Warning Emails
Enable Send Warning Emails on a rule and set a Warn This Many Days Before value (e.g. 7).
When a record enters the warning window the responsible user receives a single warning email. Each record is warned only once per rule lifetime.
The responsible user is resolved in this order: user_id → responsible_id → salesperson_id. Records with no matching user field are silently skipped.
Warnings sent are tracked under the Warnings Sent tab on each rule.
Scheduling
The cron job Auto Archive: Run All Rules runs daily. Change the run hour under Auto Archive → Configuration (UTC, 0–23, default 2).
Execution order per run:
- Warning emails sent for records entering the warning window
- Each active rule's action applied to qualifying records
- Log entry written for every rule
- Digest snapshot saved
- Slack / Teams webhook posted (if configured)
A per-rule exception boundary means one failing rule never blocks the others.
Slack and Teams Webhook
Configure under Auto Archive → Configuration.
- Webhook URL
- Incoming webhook URL from Slack or Microsoft Power Automate.
- Platform
- Auto-detect (default), Slack, or Microsoft Teams. Auto-detect identifies Slack URLs by hooks.slack.com and Teams URLs by webhook.office.com or outlook.office.
- Only post when records were affected
- Suppresses the webhook post on quiet days (default on).
Click Test Webhook to send a live test message immediately.
Analytics Dashboard
Navigate to Auto Archive → Dashboard for:
- Line graph — records affected per week over time
- Bar graph — records affected broken down by rule
- Pivot table — breakdown by rule and model
The dashboard filters to real runs (Dry Run excluded) by default. Use the search bar to filter by rule, model, action type, or date range.
Digests
Navigate to Auto Archive → Digests for daily snapshots showing:
- Total records affected
- Warning emails sent
- Number of rules that ran
- Number of dry-run entries
- Per-rule breakdown with action type and record count
Multi-Company
Each rule has an optional Company field (visible only when multi-company is enabled).
| Scenario | Behaviour |
|---|---|
| Company set | Rule is scoped to that company. Action runs in that company's environment. |
| Company left empty | Rule runs for all companies via the cron's sudo() context. |
Record-level security enforces visibility automatically. Users only see rules and logs that belong to their allowed companies.
Access Rights
| Role | Rules | Logs / Warnings / Digests | Configuration |
|---|---|---|---|
| Odoo Admin (base.group_system) | Full CRUD | Full CRUD | Full access |
| Internal User (base.group_user) | Read only | Read only | No access |
Domain Expression Reference
A domain is a Python list of conditions. Each condition is a 3-item tuple: ('field', 'operator', value). Multiple conditions are AND'd by default.
Operators
| Operator | Meaning | Example |
|---|---|---|
| = | Equals | ('state', '=', 'draft') |
| != | Not equals | ('state', '!=', 'cancel') |
| > | Greater than | ('probability', '>', 50) |
| >= | Greater than or equal | ('priority', '>=', '2') |
| < | Less than | ('probability', '<', 10) |
| <= | Less than or equal | ('amount_total', '<=', 0) |
| in | Value is in a list | ('stage_id.name', 'in', ['New', 'Qualified']) |
| not in | Value is not in a list | ('state', 'not in', ['done', 'cancel']) |
| ilike | Contains (case-insensitive) | ('name', 'ilike', 'acme') |
| =ilike | Wildcard match (case-insensitive) | ('name', '=ilike', 'acme%') |
Combining Conditions
# AND (default) — both must be true
[('state', '=', 'draft'), ('amount_total', '=', 0)]
# OR — prefix with '|'
['|', ('state', '=', 'draft'), ('state', '=', 'sent')]
# NOT — prefix with '!'
['!', ('priority', '=', '3')]
CRM Examples
[('probability', '<', 20)] # Low-probability only
[('team_id.name', '=', 'Direct Sales')] # Specific sales team
[('user_id', '=', False)] # Unassigned records
[('priority', '!=', '3')] # Exclude high-priority
Sales Examples
[('state', '=', 'draft')] # Draft quotations only
[('state', '=', 'sent')] # Sent but not confirmed
[('amount_total', '=', 0)] # Zero-value orders
Purchase Examples
[('state', '=', 'draft')] # Draft RFQs only
[('partner_id.name', 'ilike', 'Acme')] # Specific vendor
Inventory Examples
[('sale_ok', '=', True)] # Saleable products only
[('detailed_type', '=', 'product')] # Storable products only
[('detailed_type', '=', 'service')] # Service products only
Support
For questions, bug reports, or feature requests contact: adamy1558@gmail.com
License
OPL-1 — Odoo Proprietary License v1.0.
See https://www.odoo.com/documentation/16.0/legal/licenses.html for details.
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