feat(task): 任务中心扫码接单(多端) —— 服务端任务状态机/端口/迁移
- Task 加 task_code/tags/display_priority/claimed_by/claimed_at/doing_at;新增 TaskClaim 流水表。
- TaskService 加 claimed/doing/completed 状态机(claim/start_doing/complete),grab 并入 claim。
- TaskRepository 加 list_published/get_by_code/update/claim/set_doing + TaskClaimRepository;挂 Database。
- 端口:
· opc /tasks/grab-by-code、/tasks/{id}/doing、/tasks/{id}/complete
· operator POST /tasks(auto task_code) + PATCH /tasks/:id
· park /park/api/tasks(大屏展示,含 scan_payload 二维码载荷)
· training /api/tasks/claim-by-code、/api/tasks/my(小程序 C 端账号→OPC 身份 find-or-create 领单)
- 迁移 0008(tasks 加列 + task_claims)已应用+stamp;seed 补 task_code/tags/grab demo。
- tests/test_task_claim.py(自包含内存库, 状态机+流水+list_published), 直接 async 校验通过。
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from app.training import db as tdb
|
||||
@@ -52,6 +53,16 @@ def list_activities(status: str | None = None) -> list[dict]:
|
||||
return rows
|
||||
|
||||
|
||||
def create_activity(data: dict) -> dict:
|
||||
row = dict(data)
|
||||
row["id"] = tdb.gen_id("E-")
|
||||
row.setdefault("mode", "offline")
|
||||
row.setdefault("status", "open")
|
||||
row.setdefault("duration_min", 90)
|
||||
tdb.insert("events", row)
|
||||
return tdb.fetch_by_id("events", row["id"])
|
||||
|
||||
|
||||
def set_activity_status(event_id: str, status: str) -> dict | None:
|
||||
if tdb.fetch_by_id("events", event_id) is None:
|
||||
return None
|
||||
@@ -136,3 +147,68 @@ def create_test(data: dict) -> dict:
|
||||
}
|
||||
tdb.insert("tests", row)
|
||||
return pack_test(tdb.fetch_by_id("tests", row["id"]))
|
||||
|
||||
|
||||
def _parse_json(raw):
|
||||
if raw is None:
|
||||
return None
|
||||
if isinstance(raw, (dict, list)):
|
||||
return raw
|
||||
try:
|
||||
return json.loads(raw)
|
||||
except (TypeError, ValueError):
|
||||
return raw
|
||||
|
||||
|
||||
# ── 调研(survey_logs 表)─────────────────────────────────────────────────
|
||||
|
||||
def list_surveys() -> list[dict]:
|
||||
rows = tdb.list_all("survey_logs", "created_at DESC")
|
||||
return [
|
||||
{
|
||||
"id": r.get("id"),
|
||||
"username": r.get("username"),
|
||||
"source": r.get("source"),
|
||||
"answers": _parse_json(r.get("answers")),
|
||||
"created_at": r.get("created_at"),
|
||||
}
|
||||
for r in rows
|
||||
]
|
||||
|
||||
|
||||
# ── 政策(policy_logs 表)─────────────────────────────────────────────────
|
||||
|
||||
def list_policies() -> list[dict]:
|
||||
rows = tdb.list_all("policy_logs", "created_at DESC")
|
||||
return [
|
||||
{
|
||||
"id": r.get("id"),
|
||||
"username": r.get("username"),
|
||||
"answers": _parse_json(r.get("answers")),
|
||||
"policies_count": r.get("policies_count"),
|
||||
"subsidies_count": r.get("subsidies_count"),
|
||||
"loans_count": r.get("loans_count"),
|
||||
"summary": r.get("summary"),
|
||||
"created_at": r.get("created_at"),
|
||||
}
|
||||
for r in rows
|
||||
]
|
||||
|
||||
|
||||
# ── 流程(plan_logs 表)───────────────────────────────────────────────────
|
||||
|
||||
def list_plans() -> list[dict]:
|
||||
rows = tdb.list_all("plan_logs", "created_at DESC")
|
||||
return [
|
||||
{
|
||||
"id": r.get("id"),
|
||||
"username": r.get("username"),
|
||||
"region": r.get("region"),
|
||||
"status": r.get("status"),
|
||||
"need_park": r.get("need_park"),
|
||||
"has_staff": r.get("has_staff"),
|
||||
"steps_count": r.get("steps_count"),
|
||||
"created_at": r.get("created_at"),
|
||||
}
|
||||
for r in rows
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user