from app.modules.audit.constants import AuditAction, AuditSource from app.modules.audit.schemas import AuditLogCreate from app.modules.audit.service import AuditService from app.modules.events.constants import ( EventAggregateType, EventPayloadKey, EventSource, EventType, ) from app.modules.events.services import EventService from app.modules.feishu.service import FeishuService from app.modules.reports.constants import ( ReportPushStatus, ReportResponseKey, ) class ReportDeliveryMixin: def push_report( self, report: dict, receive_id: str | None, receive_id_type: str, actor: str, push_run_code: str | None = None, ) -> dict: report_type = str(report.get(ReportResponseKey.REPORT_TYPE) or report.get("type") or "report") title = report.get(ReportResponseKey.TITLE) push_run = ( self._get_push_run(push_run_code) if push_run_code else self.create_push_run( report_type=report_type, title=title, receive_id=receive_id, receive_id_type=receive_id_type, actor=actor, ) ) card = FeishuService.build_basic_card( report[ReportResponseKey.TITLE], report[ReportResponseKey.LINES], ) try: result = FeishuService(self.db).send_card(card, receive_id, receive_id_type, actor) except Exception as exc: failed_run = self.update_push_run( push_run.code, ReportPushStatus.FAILED, error_message=str(exc), ) EventService(self.db).emit( event_type=EventType.REPORT_PUSH_FAILED, source=EventSource.REPORTS, aggregate_type=EventAggregateType.REPORT_PUSH_RUN, aggregate_id=failed_run.code, actor=actor, payload={ EventPayloadKey.CODE: failed_run.code, EventPayloadKey.STATUS: failed_run.status, EventPayloadKey.ERROR_MESSAGE: failed_run.error_message, }, idempotency_key=f"report-push:{failed_run.code}:{failed_run.status}", ) raise success_run = self.update_push_run( push_run.code, ReportPushStatus.SUCCESS, provider_response=result, sent=True, ) EventService(self.db).emit( event_type=EventType.REPORT_PUSH_SUCCEEDED, source=EventSource.REPORTS, aggregate_type=EventAggregateType.REPORT_PUSH_RUN, aggregate_id=success_run.code, actor=actor, payload={ EventPayloadKey.CODE: success_run.code, EventPayloadKey.STATUS: success_run.status, }, idempotency_key=f"report-push:{success_run.code}:{success_run.status}", ) AuditService(self.db).log( AuditLogCreate( actor=actor, source=AuditSource.REPORTS, action=AuditAction.REPORT_PUSH, target_id=push_run.code, response_payload={"status": ReportPushStatus.SUCCESS}, ) ) return result