# Copyright 2025 glueckkanja AG () - Christopher Rogos # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from ast import literal_eval from collections import defaultdict from odoo import models, tools class Base(models.AbstractModel): _inherit = "base" @tools.ormcache() def _tm_all_tracking_domain_fields(self): cr = self._cr cr.execute( """ SELECT id, model, name, tracking_domain FROM ir_model_fields WHERE tracking_domain is not null and tracking_domain != '' and tracking_domain != '[]' """ ) result = defaultdict(dict) for row in cr.dictfetchall(): result[row["model"]][row["name"]] = row return result def _tm_post_message(self, data): for model_name, model_data in data.items(): all_tracking_domain_fields = self._tm_all_tracking_domain_fields()[ model_name ] # check if any fields with tracking_domain if not all_tracking_domain_fields: continue record_to_remove = [] for record_id, messages_by_field in model_data.items(): fields_to_remove = [] record = self.env[model_name].browse(record_id) if not record.exists(): # if a record have been modify and then deleted # it's not need to track the change so skip it continue for field_name, _messages in messages_by_field.items(): field_data = all_tracking_domain_fields.get(field_name, False) if field_data and not record.filtered_domain( literal_eval(field_data["tracking_domain"]) ): fields_to_remove.append(field_name) for field_name in fields_to_remove: del model_data[record_id][field_name] if not model_data[record_id]: record_to_remove.append(record_id) for record_id in record_to_remove: del model_data[record_id] return super()._tm_post_message(data) def _mail_track(self, tracked_fields, initial_values): changes, tracking_value_ids = super()._mail_track( tracked_fields, initial_values ) tracking_value_field_ids = [ tracking_value_id[2]["field_id"] for tracking_value_id in tracking_value_ids ] if tracking_value_field_ids: all_tracking_domain_fields = self._tm_all_tracking_domain_fields()[ self._name ] if all_tracking_domain_fields: # remove entries that are not matching the tracking_domain of the field fields_to_remove = [] for field_name in tracked_fields: field_data = all_tracking_domain_fields.get(field_name, False) if field_data and not self.filtered_domain( literal_eval(field_data["tracking_domain"]) ): fields_to_remove.append(field_data["id"]) res_changes = [] res_tracking_value_ids = [] # remove values from tracking result for change, tracking_value_id in zip( changes, tracking_value_ids, strict=True ): if tracking_value_id[2]["field_id"] not in fields_to_remove: res_changes.append(change) res_tracking_value_ids.append(tracking_value_id) changes = res_changes tracking_value_ids = res_tracking_value_ids return changes, tracking_value_ids