Odoo Mindscape. Understand Odoo faster. Explore modules, fields, dependencies and version differences in one place instead of digging through the source code.
Module: Discuss
Entity: mail.tracking.duration.mixin
Compute Method: _compute_duration_tracking
| Inputs | Method | Outputs |
|---|---|---|
|
""" - Computes duration_tracking, a Json field stored as { <many2one_id (str)>: <duration_spent_in_seconds (int)> } + Track how long a record stays in different stages. - e.g. {"1": 1230, "2": 2220, "5": 14} + This method calculates elapsed time since the last stage change and stores the + information in the `duration_tracking` dictionary. - `_track_duration_field` must be present in the model that uses the mixin to specify on what - field to compute time spent. Besides, tracking must be activated for that field. + The dictionary keys are: - e.g. - class MyModel(models.Model): - _name = 'my.model' - _track_duration_field = "tracked_field" + * d (datetime): + The exact UTC datetime the record added the current state. + * s (stage id): + The unique ID of the *current* stage the record is in. - tracked_field = fields.Many2one('tracked.model', tracking=True) + <stage_id> (int): + A running total of accumulated time (in minutes) spent in previous states, mapping + stage IDs to minutes. + + Example: + {"d":"2025-11-21 15:34:28","s":3, "1":172814,"2":86401 , '0': 12 } """ - field = self.env['ir.model.fields'].sudo().search_fetch([ - ('model', '=', self._name), - ('name', '=', self._track_duration_field), - ], ['id'], limit=1) - if ( - self._track_duration_field not in self._track_get_fields() - or self._fields[self._track_duration_field].type != 'many2one' - ): - self.duration_tracking = False - raise ValueError(_( - 'Field ā%(field)sā on model ā%(model)sā must be of type Many2one and have tracking=True for the computation of duration.', - field=self._track_duration_field, model=self._name - )) - if self.ids: - self.env['mail.tracking.value'].flush_model() - self.env['mail.message'].flush_model() - trackings = self.env.execute_query_dict(SQL(""" - SELECT m.res_id, - v.create_date, - v.old_value_integer - FROM mail_tracking_value v - LEFT JOIN mail_message m - ON m.id = v.mail_message_id - AND v.field_id = %(field_id)s - WHERE m.model = %(model_name)s - AND m.res_id IN %(record_ids)s - ORDER BY v.id - """, - field_id=field.id, model_name=self._name, record_ids=tuple(self.ids), - )) - else: - trackings = [] + now = self.env.cr.now() for record in self: - record_trackings = [tracking for tracking in trackings if tracking['res_id'] == record._origin.id] - record.duration_tracking = record._get_duration_from_tracking(record_trackings) + duration_dict = record.duration_tracking or {} + last_stage_id = duration_dict.get('s') + if last_stage_id is not None and duration_dict.get('d'): + old_update = fields.Datetime.to_datetime(duration_dict['d']) + duration_dict[str(last_stage_id)] = duration_dict.get(str(last_stage_id), 0) + int((now - old_update) / timedelta(minutes=1)) + # update last stage / datetime + duration_dict['s'] = record[record._track_duration_field].id or 0 + duration_dict['d'] = self.env.cr.now() + record.duration_tracking = duration_dict |
|
