import logging from mission.payload_processors import apply_mission_payload_processor from notifier.models import NotificationEventKeyEnum from notifier.services import enqueue_notification_event logger = logging.getLogger(__name__) def _build_mission_payload(mission) -> dict: participant_names = list( mission.get_participants().values_list("employee__name", flat=True) ) content_type = getattr(mission.content_type, "model", None) return { "mission_id": mission.id, "merchant_id": mission.merchant_id, "description": mission.description, "category_id": mission.category_id, "category_name": mission.category.name, "is_urgent": mission.is_urgent, "is_completed": mission.is_completed, "is_cancelled": mission.is_cancelled, "creator_id": mission.creator_id, "creator_name": getattr(mission.creator, "name", ""), "participant_names": participant_names, "participant_names_display": "、".join(participant_names) if participant_names else "无", "content_type": content_type or "", "content_id": mission.content_id or "", "payload_processor": getattr(mission.category, "payload_processor", "") or "", } def _build_reply_payload(reply) -> dict: return { "reply_id": reply.id, "reply_content": reply.content, "reply_content_short": (reply.content or "")[:100], "responder_id": reply.responder_id, "responder_name": getattr(reply.responder, "name", ""), "ends_task": reply.ends_task, "is_rejected": reply.is_rejected, "replied_at": reply.replied_at.isoformat() if reply.replied_at else "", "rejected_at": reply.rejected_at.isoformat() if reply.rejected_at else "", } def _enqueue(*, event_key: str, merchant_id: int, payload: dict) -> None: task_id = enqueue_notification_event( event_key=event_key, merchant_id=merchant_id, payload=payload, ) logger.info( "[mission.handlers] queued notifier event: event_key=%s merchant_id=%s task_id=%s", event_key, merchant_id, task_id, ) def on_mission_created(sender, instance, created_by=None, **kwargs): payload = apply_mission_payload_processor( mission=instance, event_key=NotificationEventKeyEnum.MISSION_CREATED, payload={ **_build_mission_payload(instance), "created_by_id": getattr(created_by, "id", None), "created_by_name": getattr(created_by, "name", ""), }, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_CREATED, merchant_id=instance.merchant_id, payload=payload, ) def on_mission_replied(sender, instance, mission=None, responder=None, **kwargs): mission = mission or instance.mission payload = apply_mission_payload_processor( mission=mission, event_key=NotificationEventKeyEnum.MISSION_REPLIED, payload={ **_build_mission_payload(mission), **_build_reply_payload(instance), "responder_id": getattr(responder, "id", None), "responder_name": getattr(responder, "name", ""), }, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_REPLIED, merchant_id=mission.merchant_id, payload=payload, ) def on_mission_completed(sender, instance, completed_by=None, reply=None, **kwargs): payload = { **_build_mission_payload(instance), "completed_by_id": getattr(completed_by, "id", None), "completed_by_name": getattr(completed_by, "name", ""), } if reply is not None: payload.update(_build_reply_payload(reply)) payload = apply_mission_payload_processor( mission=instance, event_key=NotificationEventKeyEnum.MISSION_COMPLETED, payload=payload, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_COMPLETED, merchant_id=instance.merchant_id, payload=payload, ) def on_mission_reply_rejected(sender, instance, mission=None, rejected_by=None, reason=None, **kwargs): mission = mission or instance.mission payload = apply_mission_payload_processor( mission=mission, event_key=NotificationEventKeyEnum.MISSION_REPLY_REJECTED, payload={ **_build_mission_payload(mission), **_build_reply_payload(instance), "rejected_by_id": getattr(rejected_by, "id", None), "rejected_by_name": getattr(rejected_by, "name", ""), "reason": reason or "", }, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_REPLY_REJECTED, merchant_id=mission.merchant_id, payload=payload, ) def on_mission_reopened(sender, instance, reopened_by=None, rejected_reply_ids=None, **kwargs): payload = apply_mission_payload_processor( mission=instance, event_key=NotificationEventKeyEnum.MISSION_REOPENED, payload={ **_build_mission_payload(instance), "reopened_by_id": getattr(reopened_by, "id", None), "reopened_by_name": getattr(reopened_by, "name", ""), "rejected_reply_ids": rejected_reply_ids or [], "rejected_reply_ids_display": ", ".join(str(reply_id) for reply_id in (rejected_reply_ids or [])) or "无", }, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_REOPENED, merchant_id=instance.merchant_id, payload=payload, ) def on_mission_cancelled(sender, instance, cancelled_by=None, **kwargs): payload = apply_mission_payload_processor( mission=instance, event_key=NotificationEventKeyEnum.MISSION_CANCELLED, payload={ **_build_mission_payload(instance), "cancelled_by_id": getattr(cancelled_by, "id", None), "cancelled_by_name": getattr(cancelled_by, "name", ""), "cancelled_at": instance.cancelled_at.isoformat() if instance.cancelled_at else "", }, ) _enqueue( event_key=NotificationEventKeyEnum.MISSION_CANCELLED, merchant_id=instance.merchant_id, payload=payload, )