"""Persistence and visibility logging helpers for repair workflow.""" from __future__ import annotations from .shared import ( NotificationService, SignalSourceRegistry, get_audit_context, log_operation, now_cn_naive, ) class SignalSourceRepairPersistMixin: """Persist repaired links and emit visibility records.""" async def _emit_visibility_records( self, *, tenant_id: int, project_id: int, row: SignalSourceRegistry, signal_id: int, capture_status: str, ) -> None: dedupe_key = f"signal-source-repair:{int(tenant_id)}:{int(row.id)}:{int(signal_id)}" await NotificationService(self.db).create_notifications( tenant_id=int(tenant_id), user_ids=await self._active_user_ids(tenant_id=tenant_id), category="system", title="AI 已修复历史信号源关联", content=( f"项目ID: {int(project_id)}\n" f"信号源ID: {int(row.id)}\n" f"signal_id: {int(signal_id)}\n" f"status: {capture_status or 'relinked'}" ), source="ai_steward_repair", entity_type="signal_source_registry", entity_id=int(row.id), kind="info", priority="medium", status="notified", recommended_action="view_result", dedupe_key=dedupe_key, payload={ "project_id": int(project_id), "registry_id": int(row.id), "signal_id": int(signal_id), "capture_status": capture_status or "relinked", }, commit=False, ) context = get_audit_context() await log_operation( self.db, tenant_id=int(tenant_id), user_id=int(context.user_id or 1), project_id=int(project_id), entity_type="signal_source_registry", entity_id=str(int(row.id)), action="signal_source_registry.repair_link", after_data={ "signal_id": int(signal_id), "capture_status": capture_status or "relinked", }, remark="repair dirty signal source registry link", ) async def _persist_registry_link( self, *, tenant_id: int, project_id: int, row: SignalSourceRegistry, signal_id: int, capture_status: str, ) -> None: row.signal_id = int(signal_id) row.last_signal_at = now_cn_naive() await self._emit_visibility_records( tenant_id=tenant_id, project_id=project_id, row=row, signal_id=signal_id, capture_status=capture_status, ) await self.db.flush() def _build_item_result( self, *, row: SignalSourceRegistry, signal_id: int | None, capture_status: str, work_item_id: int | None, route_status: str, ) -> dict[str, object]: return { "registry_id": int(row.id), "signal_id": signal_id, "capture_status": capture_status, "work_item_id": work_item_id, "route_status": route_status, }