Skip to content

Odoo Activity Types and Scheduling: Complete Guide

DeployMonkey Team · March 23, 2026 11 min read

What Are Activities in Odoo?

Activities are actionable to-do items attached to records. Unlike chatter messages, activities have a deadline, an assigned user, and a type. They appear in the chatter, on the activity view, and in the systray menu. Any model that inherits mail.activity.mixin supports activities.

class CustomModel(models.Model):
    _name = 'custom.model'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Custom Model with Activities'

Built-In Activity Types

XML IDNameIcon
mail.mail_activity_data_emailEmailfa-envelope
mail.mail_activity_data_callCallfa-phone
mail.mail_activity_data_meetingMeetingfa-users
mail.mail_activity_data_todoTo-Dofa-tasks
mail.mail_activity_data_upload_documentUpload Documentfa-upload

Creating Custom Activity Types

<record id="activity_type_review" model="mail.activity.type">
    <field name="name">Review Required</field>
    <field name="summary">Review and approve this document</field>
    <field name="res_model_id" ref="model_sale_order"/>
    <field name="delay_count">2</field>
    <field name="delay_unit">days</field>
    <field name="delay_from">current_date</field>
    <field name="icon">fa-check-circle</field>
    <field name="default_user_id" ref="base.user_admin"/>
    <field name="chaining_type">trigger</field>
    <field name="triggered_next_type_id" ref="mail.mail_activity_data_email"/>
</record>

Activity type fields:

  • delay_count: Default deadline offset
  • delay_unit: days, weeks, or months
  • delay_from: current_date or previous_activity_type_id
  • chaining_type: suggest (recommend next) or trigger (auto-create next)
  • triggered_next_type_id: Activity type to create when this one is completed

Scheduling Activities Programmatically

Basic Scheduling

record.activity_schedule(
    'mail.mail_activity_data_call',
    date_deadline=fields.Date.today() + timedelta(days=3),
    summary='Follow up with customer',
    note='Discuss pricing and delivery schedule.',
    user_id=salesperson.id,
)

Schedule for Multiple Records

# Schedule same activity for all records in recordset
records.activity_schedule(
    'mail.mail_activity_data_todo',
    date_deadline=fields.Date.today() + timedelta(days=7),
    summary='Review pending items',
    user_id=manager.id,
)

Schedule with Custom Activity Type

record.activity_schedule(
    'my_module.activity_type_review',
    summary='Review and approve this quotation',
    note=f'Quotation amount: {record.amount_total:,.2f}',
    user_id=record.user_id.id,
)

Completing Activities

# Mark activity as done with feedback
record.activity_feedback(
    ['mail.mail_activity_data_call'],
    feedback='Customer confirmed the order. Proceed with delivery.',
)

# Mark all activities of a type as done
record.activity_feedback(
    ['mail.mail_activity_data_todo'],
    feedback='All items reviewed.',
)

# Cancel/unlink activities without feedback
record.activity_unlink(['mail.mail_activity_data_call'])

Activity-Driven Workflow

Use activity chaining to create multi-step workflows:

# Step 1: Review (auto-triggers Step 2 when done)
<record id="activity_step1_review" model="mail.activity.type">
    <field name="name">Step 1: Review</field>
    <field name="chaining_type">trigger</field>
    <field name="triggered_next_type_id" ref="activity_step2_approve"/>
</record>

# Step 2: Approve (suggests Step 3)
<record id="activity_step2_approve" model="mail.activity.type">
    <field name="name">Step 2: Approve</field>
    <field name="chaining_type">suggest</field>
    <field name="suggest_next_action_id" ref="activity_step3_execute"/>
</record>

# Step 3: Execute
<record id="activity_step3_execute" model="mail.activity.type">
    <field name="name">Step 3: Execute</field>
</record>

Querying Activities

# Find overdue activities
overdue = self.env['mail.activity'].search([
    ('date_deadline', '<', fields.Date.today()),
    ('user_id', '=', self.env.uid),
])

# Find records with pending activities
records_with_activities = self.env['sale.order'].search([
    ('activity_ids', '!=', False),
    ('activity_ids.date_deadline', '<=', fields.Date.today()),
])

# Count activities by type
activities = self.env['mail.activity'].read_group(
    [('user_id', '=', self.env.uid)],
    ['activity_type_id'],
    ['activity_type_id']
)

Automated Activity Scheduling

Schedule activities automatically on record events:

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_confirm(self):
        res = super().action_confirm()
        # Schedule delivery follow-up after confirmation
        for order in self:
            order.activity_schedule(
                'mail.mail_activity_data_todo',
                date_deadline=fields.Date.today() + timedelta(days=14),
                summary='Confirm delivery completed',
                user_id=order.user_id.id,
            )
        return res

    def write(self, vals):
        res = super().write(vals)
        # Schedule review when amount changes significantly
        if 'amount_total' in vals:
            for order in self:
                if order.amount_total > 50000:
                    order.activity_schedule(
                        'my_module.activity_type_review',
                        summary='High-value order review',
                        user_id=order.team_id.user_id.id or order.user_id.id,
                    )
        return res

Activity View

Odoo provides a dedicated activity view for managing all activities on a model:

<record id="action_sale_order_activities" model="ir.actions.act_window">
    <field name="name">Sales Activities</field>
    <field name="res_model">sale.order</field>
    <field name="view_mode">activity,tree,form</field>
</record>

Best Practices

  • Use meaningful activity types — do not use generic "To-Do" for everything
  • Set realistic deadlines — activities with past deadlines appear as overdue in the systray
  • Assign to the right user — unassigned activities are easily missed
  • Use chaining for multi-step approvals instead of scheduling all steps upfront
  • Clean up completed activities — they stay in the database unless explicitly unlinked
  • Include context in the note field so the assignee knows what to do