feat: remind only missing reporters with follow-up

This commit is contained in:
Codex 2026-05-07 21:38:50 +08:00
parent 310a82dc1a
commit 3c7b7096dd
4 changed files with 83 additions and 3 deletions

View File

@ -85,6 +85,7 @@ http://你的可访问地址:8787/auth/feishu/callback
本项目提供 Windows 任务计划脚本。任务每天触发,但发送前会读取 `data/workday-calendar.json`,只在国家法定工作日发送: 本项目提供 Windows 任务计划脚本。任务每天触发,但发送前会读取 `data/workday-calendar.json`,只在国家法定工作日发送:
- 工作日 18:00日报填写提醒 - 工作日 18:00日报填写提醒
- 工作日 18:50只提醒仍未提交的人
- 工作日 19:00日报提交汇总 - 工作日 19:00日报提交汇总
这意味着: 这意味着:

View File

@ -24,7 +24,8 @@ def send_reminder() -> dict:
payload = create_reminder_payload(f"{config.base_url}/submit") payload = create_reminder_payload(f"{config.base_url}/submit")
database = Database(config.database_path, config.employee_seed_path) database = Database(config.database_path, config.employee_seed_path)
try: try:
employees = database.list_active_employees() service = ReportService(database)
employees = service.list_reports_for_date(date.today().isoformat())["missing"]
if config.feishu_app_id and config.feishu_app_secret: if config.feishu_app_id and config.feishu_app_secret:
token = get_tenant_access_token(config.feishu_app_id, config.feishu_app_secret) token = get_tenant_access_token(config.feishu_app_id, config.feishu_app_secret)
sent = [] sent = []

View File

@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_ROOT="/root/kaikai_test"
cat > /etc/systemd/system/kaikai-daily-reminder.service <<'EOF'
[Unit]
Description=Kaikai Daily Report Reminder
[Service]
WorkingDirectory=/root/kaikai_test
ExecStart=/usr/bin/python3 -m daily_report.scheduled reminder
Type=oneshot
EOF
cat > /etc/systemd/system/kaikai-daily-reminder.timer <<'EOF'
[Unit]
Description=Run Kaikai Daily Report Reminder at 18:00
[Timer]
OnCalendar=*-*-* 18:00:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
cat > /etc/systemd/system/kaikai-daily-reminder-followup.service <<'EOF'
[Unit]
Description=Kaikai Daily Report Follow-up Reminder
[Service]
WorkingDirectory=/root/kaikai_test
ExecStart=/usr/bin/python3 -m daily_report.scheduled reminder
Type=oneshot
EOF
cat > /etc/systemd/system/kaikai-daily-reminder-followup.timer <<'EOF'
[Unit]
Description=Run Kaikai Daily Report Follow-up Reminder at 18:50
[Timer]
OnCalendar=*-*-* 18:50:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
cat > /etc/systemd/system/kaikai-daily-summary.service <<'EOF'
[Unit]
Description=Kaikai Daily Report Summary
[Service]
WorkingDirectory=/root/kaikai_test
ExecStart=/usr/bin/python3 -m daily_report.scheduled summary
Type=oneshot
EOF
cat > /etc/systemd/system/kaikai-daily-summary.timer <<'EOF'
[Unit]
Description=Run Kaikai Daily Report Summary at 19:00
[Timer]
OnCalendar=*-*-* 19:00:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now kaikai-daily-reminder.timer
systemctl enable --now kaikai-daily-reminder-followup.timer
systemctl enable --now kaikai-daily-summary.timer
systemctl list-timers --all | grep kaikai || true

View File

@ -3,6 +3,7 @@ from __future__ import annotations
import json import json
import tempfile import tempfile
import unittest import unittest
from datetime import date
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
@ -55,7 +56,7 @@ class ScheduledTest(unittest.TestCase):
self.assertIn("0/2", text) self.assertIn("0/2", text)
self.assertIn("Chen、Lin", text) self.assertIn("Chen、Lin", text)
def test_send_reminder_private_messages_all_active_employees(self) -> None: def test_send_reminder_private_messages_missing_employees_only(self) -> None:
with tempfile.TemporaryDirectory(prefix="daily-report-scheduled-") as temp: with tempfile.TemporaryDirectory(prefix="daily-report-scheduled-") as temp:
root = Path(temp) root = Path(temp)
seed_path = root / "employees.json" seed_path = root / "employees.json"
@ -87,7 +88,8 @@ class ScheduledTest(unittest.TestCase):
with patch("daily_report.config.__file__", str(fake_file)), patch.dict("os.environ", env, clear=True), patch( with patch("daily_report.config.__file__", str(fake_file)), patch.dict("os.environ", env, clear=True), patch(
"daily_report.scheduled.get_tenant_access_token", lambda app_id, app_secret: "tenant-token" "daily_report.scheduled.get_tenant_access_token", lambda app_id, app_secret: "tenant-token"
), patch("daily_report.scheduled.send_bot_interactive_message", fake_send): ), patch("daily_report.scheduled.send_bot_interactive_message", fake_send), patch("daily_report.scheduled.date") as fake_date:
fake_date.today.return_value = date(2026, 5, 7)
result = scheduled.send_reminder() result = scheduled.send_reminder()
self.assertEqual(result["mode"], "bot_private") self.assertEqual(result["mode"], "bot_private")