Skip to content

Odoo Chatter Tracked Fields: Complete Guide to Message Tracking

  • Odoo
odoo chatter tracking

Odoo Chatter Tracking fields provide developers and users with valuable insights into data changes within the platform. When you need to understand which fields are being tracked in Odoo’s chatter functionality, several methods exist to identify and customize this behavior. Furthermore, tracking field changes in Odoo’s chatter system allows businesses to maintain comprehensive audit trails and improve collaboration across teams.

Understanding Odoo’s Chatter System

Odoo Chatter Tracking. Before diving into tracked fields, it’s essential to understand what the chatter system is and how it functions across the Odoo platform.

What is the Odoo Chatter?

The chatter is Odoo’s integrated communication tool that appears at the bottom of many record forms. Additionally, it serves two primary functions:

  1. Communication: Allows users to post messages, mention colleagues, and attach files
  2. Tracking: Automatically records changes to specified fields in the record

Therefore, the chatter creates a chronological history of both manual communications and system-tracked changes, making it easier to understand a record’s history at a glance.

How Field Tracking Works in Odoo

Field tracking in Odoo works by monitoring specific fields for changes and automatically generating messages in the chatter when those changes occur. Moreover, this tracking happens at the database level and is configured in the model definition itself.

When a tracked field changes value, Odoo:

  1. Captures the old value
  2. Records the new value
  3. Creates a message showing both values
  4. Posts this message to the chatter

Consequently, users can see a complete history of important changes without manually documenting them.

Finding Tracked Fields in Odoo

Odoo Chatter Tracking. There are several methods to identify which fields are being tracked in Odoo’s chatter system. Let’s explore these approaches in detail.

Method 1: Using the Developer Mode Interface

The easiest way to check which fields are tracked is through Odoo’s interface while in developer mode. Here’s how:

  1. Activate developer mode in your Odoo instance
  2. Navigate to the record type you want to check (e.g., Sales Orders, Invoices)
  3. Click on “Edit” for any record
  4. Click “Show fields” in the developer toolbar
  5. Filter by “Tracking: On”

As a result, you’ll see all fields that are configured for tracking in the chatter. For example, on invoices, you might find around 20 tracked fields including status, payment state, and reference numbers.

Method 2: Examining the Database Structure

For a more technical approach, you can examine the message records directly in the database:

  1. Access the mail_message table in your Odoo database
  2. Filter for messages with tracking_value_ids that are not empty
  3. Check the related mail_tracking_value records to see which fields are being tracked

Furthermore, this method allows you to see the actual data structure used for tracking changes and can help in understanding the underlying mechanism.

Method 3: Reviewing the Python Model Definition

For developers, the most direct method is to examine the Python model definition:

class SaleOrder(models.Model):
    _name = 'sale.order'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    
    name = fields.Char(string='Order Reference', tracking=True)
    state = fields.Selection([
        ('draft', 'Quotation'),
        ('sent', 'Quotation Sent'),
        ('sale', 'Sales Order'),
        ('done', 'Locked'),
        ('cancel', 'Cancelled'),
    ], string='Status', tracking=True, default='draft')
    partner_id = fields.Many2one('res.partner', tracking=True)
    # Other fields...

In this example, the tracking=True parameter indicates fields that will be tracked in the chatter. Therefore, by reviewing the model code, you can definitively identify all tracked fields.

Customizing Field Tracking in Odoo

Once you understand which fields are tracked, you may want to customize this behavior for your specific needs.

Adding Tracking to Existing Fields

To add tracking to an existing field, you have two options:

Option 1: Using Odoo Studio (No Development Required)

If you have Odoo Studio enabled:

  1. Enter Edit mode for the model you want to modify
  2. Open the field properties using Studio
  3. Check the “Track Changes” option
  4. Save your changes

For example, if you have a custom field on the customer model that you want to track changes for, this method allows you to enable tracking without writing code.

Option 2: Through Python Inheritance (For Developers)

For a more permanent solution, you can extend the model in Python:

class SaleOrderInherit(models.Model):
    _inherit = 'sale.order'
    
    # Add tracking to an existing field
    commitment_date = fields.Datetime(tracking=True)
    
    # Create a new tracked field
    custom_reference = fields.Char(string='Custom Reference', tracking=True)

Moreover, this approach allows you to version-control your tracking configurations and deploy them across multiple environments.

Removing Tracking from Fields

Similarly, you might want to disable tracking for certain fields to reduce chatter noise:

class AccountMoveInherit(models.Model):
    _inherit = 'account.move'
    
    # Override the field definition to remove tracking
    invoice_date = fields.Date(string='Invoice/Bill Date', tracking=False)

As a result, changes to the invoice date would no longer generate messages in the chatter.

Advanced Tracking Features in Odoo

Beyond basic field tracking, Odoo offers several advanced features for monitoring changes.

Tracking Many2one Field Changes

When tracking Many2one relationship fields, Odoo provides additional information in the chatter:

class SaleOrder(models.Model):
    _inherit = 'sale.order'
    
    partner_id = fields.Many2one('res.partner', tracking=True)

In this case, when the customer changes, Odoo will show both the previous and new customer names in the chatter. Furthermore, it links to both records, allowing quick navigation.

Tracking Selection Field States

For selection fields like status fields, tracking is particularly useful:

class SaleOrder(models.Model):
    _inherit = 'sale.order'
    
    state = fields.Selection([
        ('draft', 'Quotation'),
        ('sent', 'Quotation Sent'),
        ('sale', 'Sales Order'),
        ('done', 'Locked'),
        ('cancel', 'Cancelled'),
    ], string='Status', tracking=True, default='draft')

Consequently, each status change generates a clear message in the chatter, creating a visual workflow history for the record.

Tracking Numeric and Boolean Fields

Numeric and boolean fields can also be tracked, providing insights into quantitative changes:

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'
    
    product_uom_qty = fields.Float(string='Quantity', tracking=True)
    price_unit = fields.Float(string='Unit Price', tracking=True)
    is_downpayment = fields.Boolean(string='Is a Downpayment', tracking=True)

As a result, price adjustments, quantity changes, and toggle state modifications are all recorded in the chatter history.

Practical Use Cases for Tracked Fields

Understanding how to implement tracked fields opens up several practical applications for businesses.

Audit Trail for Critical Business Documents

By tracking fields on invoices, orders, and contracts, you create an automatic audit trail:

class AccountMove(models.Model):
    _inherit = 'account.move'
    
    amount_total = fields.Monetary(tracking=True)
    payment_state = fields.Selection([
        ('not_paid', 'Not Paid'),
        ('in_payment', 'In Payment'),
        ('paid', 'Paid'),
        ('partial', 'Partially Paid'),
        ('reversed', 'Reversed'),
        ('invoicing_legacy', 'Invoicing App Legacy'),
    ], string="Payment Status", tracking=True)
    partner_id = fields.Many2one(tracking=True)

For instance, tracking payment status changes helps accounting teams monitor payment progression without manual logging.

Monitoring Price and Discount Changes

For sales teams, tracking pricing fields helps maintain accountability:

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'
    
    price_unit = fields.Float(tracking=True)
    discount = fields.Float(tracking=True)

Therefore, any price adjustments or special discounts are automatically documented, creating transparency in the sales process.

Tracking Approval Workflows

For approval-based processes, tracking status and responsible persons is valuable:

class PurchaseOrder(models.Model):
    _inherit = 'purchase.order'
    
    state = fields.Selection([
        ('draft', 'RFQ'),
        ('sent', 'RFQ Sent'),
        ('to approve', 'To Approve'),
        ('purchase', 'Purchase Order'),
        ('done', 'Locked'),
        ('cancel', 'Cancelled')
    ], tracking=True)
    
    user_id = fields.Many2one('res.users', tracking=True)
    approval_date = fields.Date(tracking=True)

As a result, each step in the approval process is documented with timestamps and responsible users, creating accountability.

Leveraging the Tracking Data for Reporting

The tracking data stored in Odoo can be used for analytical purposes as well.

Accessing Tracking Data Programmatically

You can access tracking data programmatically through the mail.tracking.value model:

def get_field_change_history(self, model_name, record_id, field_name):
    # Get messages with tracking values for this record
    messages = self.env['mail.message'].search([
        ('model', '=', model_name),
        ('res_id', '=', record_id),
        ('tracking_value_ids', '!=', False)
    ])
    
    # Filter tracking values for the specific field
    tracking_values = self.env['mail.tracking.value'].search([
        ('mail_message_id', 'in', messages.ids),
        ('field', '=', field_name)
    ])
    
    return tracking_values

Furthermore, this allows you to build custom reports showing how specific fields change over time across your database.

Creating Change Frequency Reports

With the tracking data, you can analyze which fields change most frequently:

def field_change_frequency(self, model_name, days=30):
    # Find messages with tracking from last X days
    date_limit = fields.Datetime.now() - timedelta(days=days)
    messages = self.env['mail.message'].search([
        ('model', '=', model_name),
        ('tracking_value_ids', '!=', False),
        ('date', '>=', date_limit)
    ])
    
    # Count changes by field
    field_counts = {}
    for message in messages:
        for tracking in message.tracking_value_ids:
            field_name = tracking.field
            field_counts[field_name] = field_counts.get(field_name, 0) + 1
    
    return sorted(field_counts.items(), key=lambda x: x[1], reverse=True)

As a result, you can identify which fields are most volatile and may require additional attention or workflow adjustments.

Best Practices for Field Tracking in Odoo

After understanding how tracking works, it’s important to follow best practices for implementation.

Only Track Meaningful Fields

While tracking is useful, too much tracking creates noise. Therefore, focus on fields that have business significance:

class ProjectTask(models.Model):
    _inherit = 'project.task'
    
    # Track important fields
    stage_id = fields.Many2one(tracking=True)  # Task stage is important to track
    user_id = fields.Many2one(tracking=True)   # Assigned user changes are important
    
    # Don't track fields that change frequently with little value
    # sequence = fields.Integer(tracking=True)  # Avoid tracking this
    # color = fields.Integer(tracking=True)     # Avoid tracking this

Consequently, your chatter will contain relevant information without overwhelming users with trivial updates.

Group Related Field Changes

When multiple related fields change together, consider using the write method to group these changes:

def update_pricing(self):
    # Instead of setting these fields individually, which would create
    # multiple tracking messages, group them in a single write
    self.write({
        'price_unit': self.calculated_price,
        'discount': self.calculated_discount,
        'tax_id': [(6, 0, self.applicable_tax_ids.ids)]
    })
    # This creates a single change event in the chatter

Moreover, this approach keeps the chatter cleaner and provides better context for the changes.

Document Tracking Decisions

When implementing custom tracking, document your decisions:

class CustomModel(models.Model):
    _name = 'custom.model'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Custom Model'
    
    # Track status changes for compliance requirements (SOX Section 404)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected')
    ], tracking=True)
    
    # Track amount changes for audit purposes
    amount = fields.Monetary(tracking=True)  # Required by finance department
    
    # Don't track these fields as they change frequently
    # last_computation_date = fields.Datetime()
    # sequence = fields.Integer()

As a result, future developers will understand why certain fields are tracked while others are not.

Troubleshooting Tracking Issues

Even with proper configuration, you might encounter issues with field tracking.

Field Changes Not Appearing in Chatter

If field changes aren’t appearing in the chatter, check the following:

  1. Verify the field has tracking=True in its definition
  2. Ensure the model inherits from mail.thread
  3. Check if changes are being made through the ORM (direct SQL won’t trigger tracking)
  4. Verify the user has access rights to see the chatter messages

For example, the model definition should look like:

class SampleModel(models.Model):
    _name = 'sample.model'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    
    tracked_field = fields.Char(tracking=True)

Furthermore, changes should be made through ORM methods like write() or form updates, not direct SQL.

Too Many Messages in Chatter

If your chatter is overwhelmed with tracking messages:

  1. Review which fields are tracked and consider reducing the number
  2. Group related changes into a single write() call
  3. Consider implementing custom tracking logic for batch operations

For instance, you might implement a custom method for batch updates:

def update_multiple_records(self, records, values):
    # Add a manual note instead of tracking each individual change
    for record in records:
        record.write(values)
        if len(records) > 1:
            record.message_post(
                body=f"Updated {len(values)} fields in a batch operation",
                subtype_id=self.env.ref('mail.mt_note').id
            )
    return True

As a result, bulk operations generate cleaner, more useful chatter history.

Enhancing Odoo’s Tracking with Custom Development

For advanced use cases, you might need to implement custom tracking behavior.

Custom Tracking Messages

You can create more descriptive tracking messages for specific fields:

class SaleOrder(models.Model):
    _inherit = 'sale.order'
    
    def write(self, vals):
        # Before the update
        for record in self:
            # Store old value if we're updating the amount
            if 'amount_total' in vals:
                old_amount = record.amount_total
        
        # Perform the standard update (with normal tracking)
        result = super(SaleOrder, self).write(vals)
        
        # After the update, add a custom tracking message
        for record in self:
            if 'amount_total' in vals and old_amount != record.amount_total:
                difference = record.amount_total - old_amount
                message = f"Order value {'increased' if difference > 0 else 'decreased'} by {abs(difference):.2f} {record.currency_id.name}"
                record.message_post(body=message)
        
        return result

Consequently, you can provide more business context in tracking messages beyond simple “changed from X to Y” notifications.

Tracking Related Fields

Standard tracking doesn’t work for related fields, but you can implement custom tracking:

class SaleOrder(models.Model):
    _inherit = 'sale.order'
    
    # Related field that we want to track
    partner_credit_limit = fields.Float(related='partner_id.credit_limit', readonly=True)
    
    @api.model
    def create(self, vals):
        record = super(SaleOrder, self).create(vals)
        # Track initial value on creation
        if record.partner_id and record.partner_id.credit_limit:
            record.message_post(body=f"Customer credit limit is {record.partner_credit_limit}")
        return record
    
    def write(self, vals):
        # Track changes to the partner
        if 'partner_id' in vals:
            for record in self:
                new_partner = self.env['res.partner'].browse(vals['partner_id'])
                if new_partner and new_partner.credit_limit:
                    record.message_post(body=f"New customer credit limit is {new_partner.credit_limit}")
        return super(SaleOrder, self).write(vals)

Therefore, you can track information even from related models, providing more context in your chatter history.

Conclusion

Understanding and configuring tracked fields in Odoo’s chatter system is essential for maintaining good record-keeping and enabling effective collaboration. Moreover, whether you’re using the interface to check existing tracking or developing custom modules with tracked fields, this knowledge helps create more transparent and auditable business processes.

To learn more about Odoo’s chatter and tracking capabilities, visit the official Odoo documentation for detailed explanations and examples from the source.

By implementing the strategies outlined in this guide, you’ll create more informative record histories that help your team understand not just what changed, but when, why, and by whom—improving accountability and communication throughout your organization.

Do you have specific questions about tracking fields in Odoo’s chatter? Share your experiences or challenges in the comments below!


Discover more from teguhteja.id

Subscribe to get the latest posts sent to your email.

Leave a Reply

WP Twitter Auto Publish Powered By : XYZScripts.com