from odoo import api, fields, models import logging _logger = logging.getLogger(__name__) class DirectivePolicy(models.Model): _name = "directive.policy" _description = "Directive Policy" _order = "sequence, id" name = fields.Char(required=True) active = fields.Boolean(default=True) sequence = fields.Integer(default=10) origin_model = fields.Char( string="Origin model", required=True, index=True, help="Техническое имя модели источника, например 'project.task'", ) event = fields.Selection( [ ("manual", "Manual"), ("on_create", "On Create"), ("on_write", "On Write"), ("on_stage", "On Stage Change"), ("on_cron", "On Cron"), ("on_callback", "При вызове метода (on_callback)"), ], required=True, index=True, default="manual", ) mode = fields.Selection( [ ("create_once", "Create once"), ("create_each_time", "Create each time"), ], required=True, default="create_once", ) use_record_template_group = fields.Boolean( default=True, help="Если включено, группа берётся из поля записи-источника directive_template_group_id.", ) template_group_id = fields.Many2one( "directive.template.group", string="Fixed template group", help="Если указано и use_record_template_group=False — будет использоваться эта группа.", ) trigger_field = fields.Char( help="Имя поля источника, например 'stage_id'." ) trigger_value_int = fields.Integer( help="Для Many2one/Integer: ожидаемое значение (например ID стадии)." ) def _policy_should_fire(self, record, payload: dict | None = None) -> bool: self.ensure_one() # Для on_callback факт вызова метода - это уже триггер. if self.event == 'on_callback': return True if not self.trigger_field: return True value = getattr(record, self.trigger_field, False) if hasattr(value, "id"): match = bool(value and value.id == self.trigger_value_int) if not match: _logger.debug("[directive.policy] ID mismatch: expected %s, got %s", self.trigger_value_int, value.id) return match try: match = (value == self.trigger_value_int) if not match: _logger.debug("[directive.policy] Value mismatch: expected %s, got %s", self.trigger_value_int, value) return match except Exception as e: _logger.error("[directive.policy] Error comparing values: %s", e) return False def _resolve_template_group(self, record): self.ensure_one() if self.use_record_template_group: return record.directive_template_group_id return self.template_group_id def apply_to_records(self, records, payload: dict | None = None): self.ensure_one() if not records: return 0 created_total = 0 for rec in records: if rec._name != self.origin_model: continue if not self._policy_should_fire(rec, payload=payload): continue group = self._resolve_template_group(rec) if not group: continue if self.mode == "create_once": existing = rec.env["directive.directive"].search_count([ ("origin_id", "=", rec.directive_origin_id.id), ("policy_id", "=", self.id), ]) if existing: continue rec._directive_create_from_group(group, policy=self) created_total += 1 return created_total