from odoo import models, fields, api import logging from markupsafe import Markup _logger = logging.getLogger(__name__) class KpiPeriodLine(models.Model): _name = 'kpi.period.line' _description = 'KPI Period Line (Worksheet)' _order = 'sequence, id' line_id = fields.Many2one('kpi.kpi.line', string='KPI Line', required=True, ondelete='cascade') name = fields.Char(string='Period', required=True) sequence = fields.Integer(string='Sequence', default=10) date_start = fields.Date(string='Start Date') date_end = fields.Date(string='End Date') realization = fields.Float(string='Realization', digits=(16, 2)) target = fields.Float(string='Target (Period)', digits=(16, 2)) state = fields.Selection([ ('draft', 'Open'), ('closed', 'Closed'), ], string='Status', default='draft') def write(self, vals): # Track changes for visualization in chatter of the parent KPI tracked_fields = {'realization', 'target', 'state'} fields_to_check = tracked_fields.intersection(vals.keys()) if fields_to_check: # Store old values to compare old_values = {rec.id: {f: rec[f] for f in fields_to_check} for rec in self} # Perform write result = super(KpiPeriodLine, self).write(vals) # Check and log for rec in self: for field in fields_to_check: old_val = old_values[rec.id].get(field) new_val = vals.get(field) # Handle comparisons safely changed = False if self._fields[field].type == 'float': if float(old_val or 0.0) != float(new_val or 0.0): changed = True else: if old_val != new_val: changed = True if changed: parent_kpi = rec.line_id.kpi_id if parent_kpi: field_label = self._fields[field].string # Format values for display (mapped selection, etc) not fully implemented here but using raw strings for now is usually fine for floats/simple selects # For State showing label would be better but raw value is understandable for "draft/closed" body = Markup("KPI Line %s - Period %s updated %s: %s → %s") % ( rec.line_id.name, rec.name, field_label, old_val, new_val ) parent_kpi.message_post(body=body) return result return super(KpiPeriodLine, self).write(vals)