chore: 保存进行中的未提交改动(企微定向推送+搜索筛选UI等)
保存合并前工作树中遗留的进行中改动,避免分支合并时丢失: - scheduler: 填报汇总改为定向推送给支局长/领导(而非广播@all) - router: JWT token 校验修复,bind token(UUID)不被误剥离 - 工作计划/计划列表: 搜索+筛选+分页 UI - 各列表 API 增加 search 参数支持 - docker-compose.backend.yml + backend/.dockerignore 纳入版本管理 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -12,7 +12,7 @@ from app.models.key_visit import KeyVisit
|
||||
from app.models.daily_note import DailyNote
|
||||
from app.models.leave import Leave
|
||||
from app.services.holidays import load_holiday_sets
|
||||
from app.utils.timezone import today_cst, is_working_day
|
||||
from app.utils.timezone import today_cst, is_working_day, parse_date
|
||||
|
||||
|
||||
def get_week_range(reference_date: date | None = None):
|
||||
@@ -22,7 +22,7 @@ def get_week_range(reference_date: date | None = None):
|
||||
return monday, sunday
|
||||
|
||||
|
||||
async def get_dashboard_stats(db: AsyncSession, reference_date: date | None = None) -> dict:
|
||||
async def get_dashboard_stats(db: AsyncSession, reference_date: date | None = None, user_id: str = "", role: str = "") -> dict:
|
||||
"""Get dashboard statistics for a given week (defaults to current)."""
|
||||
monday, sunday = get_week_range(reference_date)
|
||||
today = date.today()
|
||||
@@ -51,12 +51,22 @@ async def get_dashboard_stats(db: AsyncSession, reference_date: date | None = No
|
||||
)
|
||||
)).scalar() or 0
|
||||
|
||||
# Overdue plans (status=计划中, plan_date < today). Managers see only own.
|
||||
overdue_q = select(func.count(WorkPlan.id)).where(
|
||||
WorkPlan.status == "计划中",
|
||||
WorkPlan.plan_date < today,
|
||||
)
|
||||
if role == "manager":
|
||||
overdue_q = overdue_q.where(WorkPlan.manager_id == UUID(user_id))
|
||||
overdue_plans = (await db.execute(overdue_q)).scalar() or 0
|
||||
|
||||
return {
|
||||
"week_visits": visits_count,
|
||||
"work_plans": plans_count,
|
||||
"mini_business": mini_biz_count,
|
||||
"key_visits": key_visit_count,
|
||||
"week_leaves": leaves_count,
|
||||
"overdue_plans": overdue_plans,
|
||||
"week_start": str(monday),
|
||||
"week_end": str(sunday),
|
||||
}
|
||||
@@ -180,8 +190,18 @@ async def get_weekly_report(
|
||||
|
||||
visits_data = []
|
||||
for gid, gvisits in groups.items():
|
||||
# Determine the "primary" — first record in group (the creator's)
|
||||
primary = gvisits[0]
|
||||
# Determine the "primary" — the creator's record (not a companion copy)
|
||||
def _is_companion_copy(v) -> bool:
|
||||
content = (v.communication_content or "").strip()
|
||||
# New-style: has "(协同XXX)" suffix
|
||||
if content.endswith(")") and "(协同" in content:
|
||||
return True
|
||||
# Old-style: empty draft created for companion
|
||||
if not content:
|
||||
return True
|
||||
return False
|
||||
creator_records = [v for v in gvisits if not _is_companion_copy(v)]
|
||||
primary = creator_records[0] if creator_records else gvisits[0]
|
||||
companion_names_resolved = [user_map.get(c, str(c)) for c in (primary.companions or [])]
|
||||
companion_names_resolved.extend(primary.companion_names or [])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user