feat: 系统设置新增通报时间配置 + 亮灯表30天滚动窗口 + 相关人员文案统一 + 周报数据补全
- 亮灯表从自然月改为30天滚动窗口(30/60天阈值),解决月底覆盖断崖 - 系统设置新增「定时通报时间」选择器,支局长可配置每日企微通报时刻 - 新增 SystemConfig 键值表 + scheduler_manager APScheduler 运行时重调度 - 拜访记录/导入模板/弹窗表单统一「同访人员」→「相关人员」 - 仪表盘周报数据补全:companion_names_resolved、visitor_name/phone 等字段 - 新增 weekly_report_template.xlsx 模板文件 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""APScheduler singleton — allows runtime reschedule of notification jobs."""
|
||||
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
|
||||
_scheduler: AsyncIOScheduler | None = None
|
||||
|
||||
|
||||
def get_scheduler() -> AsyncIOScheduler:
|
||||
"""Lazy-init and return the global scheduler."""
|
||||
global _scheduler
|
||||
if _scheduler is None:
|
||||
_scheduler = AsyncIOScheduler()
|
||||
return _scheduler
|
||||
|
||||
|
||||
async def reschedule_daily_check(hour: int, minute: int):
|
||||
"""Update the daily_check cron job to a new time."""
|
||||
sched = get_scheduler()
|
||||
# Remove and re-add — APScheduler reschedule_job is inconsistent with cron triggers
|
||||
try:
|
||||
sched.remove_job("daily_check")
|
||||
except Exception:
|
||||
pass
|
||||
from app.services.scheduler import check_daily_reporting
|
||||
from app.database import async_session
|
||||
|
||||
async def _wrapper():
|
||||
async with async_session() as db:
|
||||
await check_daily_reporting(db)
|
||||
|
||||
sched.add_job(_wrapper, "cron", hour=hour, minute=minute, id="daily_check")
|
||||
|
||||
|
||||
def start_scheduler(notification_hour: int = 17, notification_minute: int = 30):
|
||||
"""Start the scheduler with configured notification times."""
|
||||
sched = get_scheduler()
|
||||
|
||||
from app.services.scheduler import check_daily_reporting, check_overdue_plans
|
||||
from app.database import async_session
|
||||
|
||||
async def _daily():
|
||||
async with async_session() as db:
|
||||
await check_daily_reporting(db)
|
||||
|
||||
async def _overdue():
|
||||
async with async_session() as db:
|
||||
await check_overdue_plans(db)
|
||||
|
||||
sched.add_job(_daily, "cron", hour=notification_hour, minute=notification_minute, id="daily_check")
|
||||
sched.add_job(_overdue, "cron", hour=9, minute=0, id="overdue_check")
|
||||
sched.start()
|
||||
|
||||
|
||||
def shutdown_scheduler():
|
||||
"""Shutdown the scheduler gracefully."""
|
||||
global _scheduler
|
||||
if _scheduler is not None:
|
||||
_scheduler.shutdown(wait=False)
|
||||
_scheduler = None
|
||||
Reference in New Issue
Block a user