c4e8a3b790
scheduler.py: - 未填报经理 → 模板卡片消息(标题+描述+「去填报」按钮) - 支局长/领导 → Markdown 每日填报汇总(markdown) - 文本消息作为降级方案 wecom.py API: - remind: 模板卡片优先 → 降级文本 - announcement: Markdown 优先 → 降级文本 Co-Authored-By: Claude <noreply@anthropic.com>
91 lines
3.4 KiB
Python
91 lines
3.4 KiB
Python
from datetime import date, datetime
|
|
from sqlalchemy import select, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from app.models.visit import Visit
|
|
from app.models.daily_note import DailyNote
|
|
from app.models.user import User
|
|
from app.services.wecom import wecom_client
|
|
from app.utils.timezone import today_cst
|
|
|
|
|
|
async def check_daily_reporting(db: AsyncSession) -> dict:
|
|
"""Check today's reporting progress and send wecom reminders to managers who haven't reported."""
|
|
today = today_cst()
|
|
weekday = today.weekday()
|
|
if weekday >= 5: # Skip weekends
|
|
return {"status": "weekend", "date": str(today)}
|
|
|
|
# Get all managers with wecom_userid
|
|
result = await db.execute(
|
|
select(User).where(User.role == "manager", User.wecom_userid.isnot(None))
|
|
)
|
|
managers = result.scalars().all()
|
|
|
|
if not managers:
|
|
return {"status": "ok", "date": str(today), "total_managers": 0, "reported": 0, "not_reported": 0}
|
|
|
|
# Get managers who have reported today
|
|
reported_visits = await db.execute(
|
|
select(Visit.manager_id).where(Visit.visit_date == today)
|
|
)
|
|
reported_notes = await db.execute(
|
|
select(DailyNote.manager_id).where(DailyNote.note_date == today)
|
|
)
|
|
reported_map = {str(uid): True for uid, in reported_visits.all()}
|
|
for uid, in reported_notes.all():
|
|
reported_map[str(uid)] = True
|
|
|
|
not_reported = []
|
|
reported_names = []
|
|
for m in managers:
|
|
if str(m.id) in reported_map:
|
|
reported_names.append(m.name)
|
|
else:
|
|
not_reported.append(m)
|
|
|
|
# 1. Send template card to not-reported managers (tap to open app)
|
|
if not_reported:
|
|
user_ids = [m.wecom_userid for m in not_reported if m.wecom_userid]
|
|
if user_ids:
|
|
desc = f"{today} | 已填报 {len(reported_names)}/{len(managers)} 人"
|
|
success = await wecom_client.send_template_card(
|
|
user_ids=user_ids,
|
|
title="📋 今日填报提醒",
|
|
desc=desc,
|
|
url="https://qj.dhdx.fun/m",
|
|
btn_text="去填报",
|
|
)
|
|
# Fallback to text
|
|
if not success:
|
|
names_text = "、".join(m.name for m in not_reported)
|
|
await wecom_client.send_text_message(
|
|
user_ids,
|
|
f"📋 今日填报提醒\n\n{desc}\n未填报:{names_text}\n\n请尽快完成填报 🙏\nhttps://qj.dhdx.fun/m",
|
|
)
|
|
|
|
# 2. Send summary to director
|
|
directors = await db.execute(
|
|
select(User).where(User.role.in_(["director", "leader"]), User.wecom_userid.isnot(None))
|
|
)
|
|
for d in directors.scalars().all():
|
|
if managers:
|
|
pct = len(reported_map) / len(managers) * 100
|
|
summary = (
|
|
f"## 📊 今日填报汇总\n\n"
|
|
f"> 日期:{today}\n"
|
|
f"> 填报率:**{pct:.0f}%** ({len(reported_map)}/{len(managers)})\n\n"
|
|
)
|
|
if not_reported:
|
|
summary += "**未填报:**\n" + "".join(f"- {m.name}\n" for m in not_reported)
|
|
else:
|
|
summary += "✅ 全体已完成今日填报"
|
|
await wecom_client.send_markdown_message(summary) # broadcast for director visibility
|
|
|
|
return {
|
|
"status": "ok",
|
|
"date": str(today),
|
|
"total_managers": len(managers),
|
|
"reported": len(reported_map),
|
|
"not_reported": len(not_reported),
|
|
}
|