Files
zkxw/backend/app/services/oa_wechat_notify.py
T

102 lines
3.2 KiB
Python

"""OA 任务创建后服务号通知(commit 后异步)。"""
from __future__ import annotations
import logging
import threading
from datetime import datetime
from typing import Iterable, List
from app.core.database import SessionLocal
from app.models.models import OaInstance, OaTask, SysUser
from app.services.wechat_mp_message import send_oa_approval_notify, send_oa_cc_notify
logger = logging.getLogger(__name__)
def build_oa_detail_pagepath(*, instance_id: str, task_id: str, mode: str) -> str:
# 无前导 /
return (
f"pages/oa/webview/index?instanceId={instance_id}"
f"&taskId={task_id}&mode={mode}"
)
def _send_one(db, task: OaTask) -> None:
uid = (task.assignee_user_id or "").strip()
if not uid:
return
user = db.query(SysUser).filter(SysUser.id == uid, SysUser.del_flag == 0).first()
mp = (getattr(user, "wx_mp_openid", None) or "").strip() if user else ""
if not mp:
logger.info("oa wx notify skip: no mp_openid user=%s task=%s", uid, task.id)
return
inst = (
db.query(OaInstance)
.filter(OaInstance.id == task.instance_id, OaInstance.del_flag == 0)
.first()
)
title = (inst.title if inst else "") or (task.node_name or "审批")
applicant = ""
if inst and inst.initiator_user_id:
ini = db.query(SysUser).filter(SysUser.id == inst.initiator_user_id).first()
applicant = (ini.nick_name if ini else "") or ""
time_text = datetime.now().strftime("%Y-%m-%d %H:%M")
node_name = task.node_name or ""
if task.task_type == "approval" and (task.status or "") == "pending":
pagepath = build_oa_detail_pagepath(
instance_id=task.instance_id, task_id=task.id, mode="approve"
)
send_oa_approval_notify(
mp_openid=mp,
pagepath=pagepath,
title=title,
applicant=applicant,
node_name=node_name,
time_text=time_text,
)
elif task.task_type == "cc":
pagepath = build_oa_detail_pagepath(
instance_id=task.instance_id, task_id=task.id, mode="view"
)
send_oa_cc_notify(
mp_openid=mp,
pagepath=pagepath,
title=title,
applicant=applicant,
node_name=node_name,
time_text=time_text,
)
def notify_oa_tasks_sync(task_ids: Iterable[str]) -> None:
ids = [str(x).strip() for x in task_ids if str(x).strip()]
if not ids:
return
db = None
try:
db = SessionLocal()
tasks = (
db.query(OaTask)
.filter(OaTask.id.in_(ids), OaTask.del_flag == 0)
.all()
)
for t in tasks:
try:
_send_one(db, t)
except Exception:
logger.exception("oa wx notify failed task=%s", t.id)
except Exception:
logger.exception("oa wx notify batch failed ids=%s", ids)
finally:
if db is not None:
db.close()
def schedule_oa_task_notifies(task_ids: List[str]) -> None:
ids = [str(x).strip() for x in (task_ids or []) if str(x).strip()]
if not ids:
return
threading.Thread(
target=notify_oa_tasks_sync, args=(ids,), daemon=True, name="oa-wx-notify"
).start()