diff --git a/README.md b/README.md index 8eacd66..8494542 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ http://你的可访问地址:8787/auth/feishu/callback 本项目提供 Windows 任务计划脚本。任务每天触发,但发送前会读取 `data/workday-calendar.json`,只在国家法定工作日发送: - 工作日 18:00:日报填写提醒 +- 工作日 18:50:只提醒仍未提交的人 - 工作日 19:00:日报提交汇总 这意味着: diff --git a/daily_report/scheduled.py b/daily_report/scheduled.py index 5509f18..b3b0668 100644 --- a/daily_report/scheduled.py +++ b/daily_report/scheduled.py @@ -24,7 +24,8 @@ def send_reminder() -> dict: payload = create_reminder_payload(f"{config.base_url}/submit") database = Database(config.database_path, config.employee_seed_path) 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: token = get_tenant_access_token(config.feishu_app_id, config.feishu_app_secret) sent = [] diff --git a/scripts/install-linux-timers.sh b/scripts/install-linux-timers.sh new file mode 100644 index 0000000..f78f9e3 --- /dev/null +++ b/scripts/install-linux-timers.sh @@ -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 diff --git a/tests/test_scheduled.py b/tests/test_scheduled.py index de7f80d..60933e2 100644 --- a/tests/test_scheduled.py +++ b/tests/test_scheduled.py @@ -3,6 +3,7 @@ from __future__ import annotations import json import tempfile import unittest +from datetime import date from pathlib import Path from unittest.mock import patch @@ -55,7 +56,7 @@ class ScheduledTest(unittest.TestCase): self.assertIn("0/2", 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: root = Path(temp) 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( "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() self.assertEqual(result["mode"], "bot_private")