Audit Logs
Contents
Audit Logs#
This article explains how the audit modules work in OpenSPP and how to customize them, using a practical example and a working sample module. The audit stack consists of spp_audit_log (core models and UI), spp_audit_post (optional chatter posting), and spp_audit_config (preconfigured rules).
Core Models
The audit stack provides core logging and optional posting with the following key components:
spp.audit.rule: Configures what to log per model. Fields includemodel_id,field_to_log_ids, and toggles forlog_create,log_write,log_unlink, plusview_logsto add a context action.spp.audit.log: Stores individual change entries includingaudit_rule_id,user_id,model_id,res_id,method, and formatteddata_html.(From
spp_audit_post)spp.audit.ruleadds parent linking (parent_id,child_ids,field_id) andspp.audit.logaddsparent_model_id,parent_res_ids_str, andparent_data_htmlfor posting to parent records.
Key Features
Dynamic method decoration on target models (
create,write,_write,unlink) when a rule is created or updatedField-level selection via
field_to_log_idsand automatic formatting for selections, relational fields, and datetime valuesOptional action menu "View logs" bound to the target model when
view_logsis enabledOptional posting of audit messages to the target record or its parent model chatter (
spp_audit_post)Preconfigured default rules installed via
spp_audit_config(data/audit_rule_data.xml)
Prerequisites#
Solid understanding of Odoo 17 module development, including Python, XML, and XPath.
Ensure the following modules are installed: SPP Audit Config, SPP Audit Log, SPP Audit Post (optional).
To set up OpenSPP for development, please refer to the Development Setup Guide.
Module Structure#
A typical audit customization module follows the standard Odoo module structure. Here’s the structure for the example module, spp_audit_log_custom:
spp_audit_log_custom/
├── __init__.py
├── __manifest__.py
├── models/
│ ├── __init__.py
│ └── spp_audit_rule.py
├── views/
│ └── spp_audit_rule_views.xml
├── security/
│ └── ir.model.access.csv
└── data/
└── audit_rule_data.xml
Step-by-Step Guide#
In this example, we customize the audit rule to include an active flag, allowing rules to be enabled or disabled without deletion.
A working sample module is available at this link.
Create the Module Scaffold#
Start by creating a new directory for your module (e.g., spp_audit_log_custom) and populate it
with the basic Odoo module files (__init__.py, __manifest__.py) and the directory structure shown above.
Define Module Manifest#
Create a manifest file with the correct dependencies and data files:
{
"name": "OpenSPP Audit Customizations",
"summary": "Custom extensions for OpenSPP Audit",
"category": "OpenSPP",
"version": "17.0.1.0.0",
"author": "Your Organization",
"website": "https://your-website.com",
"license": "LGPL-3",
"depends": [
"spp_audit_log",
# "spp_audit_post", # include if you extend or rely on chatter posting
],
"data": [
"views/spp_audit_rule_views.xml",
# "security/ir.model.access.csv", # not needed if you do not add new models
# "data/audit_rule_data.xml", # optional preconfigured rules
],
"application": False,
"installable": True,
"auto_install": False,
}
Extend the Audit Rule Model#
Create models/spp_audit_rule.py and update models/__init__.py:
from odoo import fields, models
class CustomAuditRule(models.Model):
_inherit = "spp.audit.rule"
active = fields.Boolean(
default=True,
help="If unchecked, the rule can be treated as inactive in your custom logic",
)
Create View Extensions#
Create views/spp_audit_rule_views.xml and add it to the manifest:
<odoo>
<record id="view_custom_audit_log_form" model="ir.ui.view">
<field name="name">view_custom_audit_log_form</field>
<field name="model">spp.audit.rule</field>
<field name="inherit_id" ref="spp_audit_log.spp_audit_rule_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<field name="active" />
</xpath>
</field>
</record>
</odoo>
Add Security Access (Optional)#
If you introduce new models, add access rights. For simple field additions, this is not required. Example:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_custom_spp_audit_rule,custom.spp.audit.rule,spp_audit_log.model_spp_audit_rule,base.group_system,1,1,1,0
Group ID:
g2p_registry_base.group_g2p_registrarfor Registrar AccessGroup ID:
g2p_registry_base.group_g2p_adminfor Admin Access.
Add Preconfigured Rules (Optional)#
Seed rules using data/audit_rule_data.xml and the spp.audit.rule.create_rules helper:
<odoo>
<data noupdate="1">
<function model="spp.audit.rule" name="create_rules">
<value name="rule_name">My Registry Rule</value>
<value name="model">res.partner</value>
<value name="fields_to_log" eval="['name', 'gender', 'birthdate']" />
<value name="view_logs" eval="True" />
</function>
</data>
</odoo>
For parent/child rules (requires spp_audit_post), also pass parent_rule_name and connecting_field_name.
Install and Test#
Install or upgrade the module through the Apps menu.
Create or update records in the configured models (e.g., Individual or Group Registry).
Open Audit Log → Audit → Log to review entries.
On a specific record, use Action → View logs (if enabled) to see related entries.
Best Practices#
Use Targeted Field Lists: Keep field_to_log_ids focused on business-critical fields.
References#
For more information on extending OpenSPP modules, refer to:
Audit module sources:
openspp.org