在Odoo中追踪员工更新PostgreSQL Modules表的字段变更
Hey there! Let's get this change tracking set up for your Modules model in Odoo. Here's a practical, step-by-step solution that logs every field change whenever an employee updates a record:
We need a dedicated model to store all change history. This will keep track of who made the change, what was modified, when it happened, and which module record it relates to.
from odoo import models, fields, api from odoo.tools import html_escape class ModuleChangeLog(models.Model): _name = 'module.change.log' _description = 'Module Change History Log' _order = 'create_date desc' # Show latest changes first module_id = fields.Many2one('modules', string='Related Module', required=True, ondelete='cascade') employee_id = fields.Many2one('employee', string='Updated By', required=True) change_details = fields.Html(string='Change Breakdown') create_date = fields.Datetime(string='Update Time', default=fields.Datetime.now, readonly=True)
write() Method in Your Modules Model This is where we'll capture the before-and-after values of fields being updated, compare them, and generate a log entry.
class Modules(models.Model): _inherit = 'modules' def write(self, vals): # Capture current field values BEFORE the update pre_update_values = {rec.id: {field: rec[field] for field in self.fields_get()} for rec in self} # Run the original write operation to save changes result = super(Modules, self).write(vals) # Generate change logs for each updated record current_employee = self.env.user.employee_id # Assumes your users are linked to Employee records if not current_employee: return result # Skip logging if no employee is linked to the user for rec in self: changes = [] post_update_values = {field: rec[field] for field in self.fields_get()} # Compare each modified field's pre and post values for field_name in vals.keys(): field = self._fields[field_name] pre_val = pre_update_values[rec.id][field_name] post_val = post_update_values[field_name] # Format values for readability based on field type if field.type == 'many2one': pre_display = pre_val.display_name if pre_val else 'None' post_display = post_val.display_name if post_val else 'None' elif field.type in ['one2many', 'many2many']: pre_display = ', '.join([item.display_name for item in pre_val]) if pre_val else 'None' post_display = ', '.join([item.display_name for item in post_val]) if post_val else 'None' elif field.type == 'datetime': pre_display = fields.Datetime.to_string(pre_val) if pre_val else 'None' post_display = fields.Datetime.to_string(post_val) if post_val else 'None' else: pre_display = str(pre_val) if pre_val is not None else 'None' post_display = str(post_val) if post_val is not None else 'None' # Only log if the value actually changed if pre_display != post_display: changes.append(f"<b>{field.string}</b>: {html_escape(pre_display)} → {html_escape(post_display)}") # Create a log entry if there are actual changes if changes: self.env['module.change.log'].create({ 'module_id': rec.id, 'employee_id': current_employee.id, 'change_details': '<br>'.join(changes) }) return result
Don't forget to add access rules so employees can view and create log entries. Add this to your security/ir.model.access.csv file:
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_module_change_log_user,module.change.log.user,model_module_change_log,base.group_user,1,0,1,0 access_module_change_log_manager,module.change.log.manager,model_module_change_log,base.group_system,1,1,1,1
To make it simple to view change logs directly from a Modules record, add a smart button to your form view:
<!-- Add this to your views/modules_view.xml --> <record id="modules_form_view_inherit" model="ir.ui.view"> <field name="name">modules.form.view.inherit</field> <field name="model">modules</field> <field name="inherit_id" ref="your_base_module.modules_form_view"/> <!-- Replace with your original form view reference --> <field name="arch" type="xml"> <header position="inside"> <button name="%(module_change_log_action)d" type="action" icon="fa-history" string="Change Logs"/> </header> </field> </record> <record id="module_change_log_action" model="ir.actions.act_window"> <field name="name">Module Change History</field> <field name="res_model">module.change.log</field> <field name="view_mode">tree,form</field> <field name="domain">[('module_id', '=', active_id)]</field> <field name="context">{'default_module_id': active_id}</field> </record>
Quick Notes:
- Ensure your
res.usersrecords have a linkedemployee_idfield (you might need to add this if it doesn't exist already). - You can extend the field type handling (e.g., add support for selection fields to show human-readable labels instead of raw values).
- This implementation logs all changes made via the
write()method, including bulk updates and individual record edits.
内容的提问来源于stack exchange,提问作者Mingg Lex

