fix(操作统计): 上传备注改为按任务负责人归因,历史数据可回溯
- 备注统计不用 task_logs(历史无record日志),改为 task_records 按任务 assignee 归因 - 排除系统自动生成的备注(以'['开头的接收/转交/撤回等),只计手动上传 - 移除 add_task_record 冗余的 record 日志(不再用于统计) - 不改数据库,历史182条备注也能正确归属到人
This commit is contained in:
@ -483,29 +483,29 @@ async def get_user_operations(
|
||||
since: datetime | None = None,
|
||||
until: datetime | None = None,
|
||||
) -> list[UserOperation]:
|
||||
"""上帝视角 — 统计**全部人员**的操作次数(按时段过滤 task_logs)。
|
||||
"""上帝视角 — 统计**全部人员**的操作次数(按时段过滤)。
|
||||
|
||||
返回所有 IRIS 部门人员(该时段无操作的计 0),并追加有操作记录但不在
|
||||
人员清单中的账号(如历史/已离职)。
|
||||
|
||||
操作口径:
|
||||
- 接收: action_type='receive'
|
||||
- 转交: action_type='complete'(完工并移交下一道工序)
|
||||
- 上传备注: action_type='record'(工人手动追加的进度记录)
|
||||
操作口径(均不修改数据库):
|
||||
- 接收: task_logs.action_type='receive'(按操作人)
|
||||
- 转交: task_logs.action_type='complete'(按操作人)
|
||||
- 上传备注: task_records 按**任务负责人**归因(排除系统自动生成的
|
||||
以 '[' 开头的备注,如 "[接收] 操作员已确认接收"),历史数据可回溯
|
||||
"""
|
||||
from app.models.task_log import TaskLog
|
||||
from app.models.task import Task, TaskRecord
|
||||
from app.core.mom_database import MomSessionLocal
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import text, or_
|
||||
|
||||
# ── 1. 统计 task_logs 操作次数(按 operator_id 聚合)──
|
||||
# ── 1. 接收 / 转交(task_logs 按 operator_id 聚合)──
|
||||
rcv = func.count().filter(TaskLog.action_type == "receive")
|
||||
cpl = func.count().filter(TaskLog.action_type == "complete")
|
||||
rcd = func.count().filter(TaskLog.action_type == "record")
|
||||
|
||||
stmt = (
|
||||
select(TaskLog.operator_id, rcv.label("receive"), cpl.label("complete"), rcd.label("record"))
|
||||
select(TaskLog.operator_id, rcv.label("receive"), cpl.label("complete"))
|
||||
.where(
|
||||
TaskLog.action_type.in_(["receive", "complete", "record"]),
|
||||
TaskLog.action_type.in_(["receive", "complete"]),
|
||||
TaskLog.operator_id.isnot(None),
|
||||
)
|
||||
.group_by(TaskLog.operator_id)
|
||||
@ -514,11 +514,27 @@ async def get_user_operations(
|
||||
stmt = stmt.where(TaskLog.created_at >= since)
|
||||
if until:
|
||||
stmt = stmt.where(TaskLog.created_at <= until)
|
||||
op_rows = (await db.execute(stmt)).all()
|
||||
op_map = {r[0]: (r[1] or 0, r[2] or 0) for r in op_rows}
|
||||
|
||||
result = await db.execute(stmt)
|
||||
op_map = {r[0]: (r[1] or 0, r[2] or 0, r[3] or 0) for r in result.all()}
|
||||
# ── 2. 上传备注(task_records 按任务 assignee 归因,排除系统自动备注)──
|
||||
rcd_stmt = (
|
||||
select(Task.assignee_id, func.count(TaskRecord.id))
|
||||
.join(Task, TaskRecord.task_id == Task.id)
|
||||
.where(
|
||||
Task.assignee_id.isnot(None),
|
||||
or_(TaskRecord.remark.is_(None), ~TaskRecord.remark.like("[%")),
|
||||
)
|
||||
.group_by(Task.assignee_id)
|
||||
)
|
||||
if since:
|
||||
rcd_stmt = rcd_stmt.where(TaskRecord.created_at >= since)
|
||||
if until:
|
||||
rcd_stmt = rcd_stmt.where(TaskRecord.created_at <= until)
|
||||
rcd_rows = (await db.execute(rcd_stmt)).all()
|
||||
record_map = {r[0]: r[1] or 0 for r in rcd_rows}
|
||||
|
||||
# ── 2. 获取全部 MOM 用户清单(IRIS 部门)──
|
||||
# ── 3. 获取全部 MOM 用户清单(IRIS 部门)──
|
||||
users: list[dict] = []
|
||||
try:
|
||||
dbm = MomSessionLocal()
|
||||
@ -540,19 +556,19 @@ async def get_user_operations(
|
||||
except Exception:
|
||||
users = []
|
||||
|
||||
# ── 3. 合并:所有人员 + 有操作但不在清单的账号 ──
|
||||
# ── 4. 合并:所有人员 + 有操作但不在清单的账号 ──
|
||||
merged: dict[str, dict] = {}
|
||||
for u in users:
|
||||
merged[u["username"]] = {"name": u["full_name"], "rcv": 0, "cpl": 0, "rcd": 0}
|
||||
for uid, (r, c, rd) in op_map.items():
|
||||
if uid in merged:
|
||||
merged[uid]["rcv"] = r
|
||||
merged[uid]["cpl"] = c
|
||||
merged[uid]["rcd"] = rd
|
||||
else:
|
||||
merged[uid] = {"name": uid, "rcv": r, "cpl": c, "rcd": rd}
|
||||
for uid in set(op_map.keys()) | set(record_map.keys()):
|
||||
if uid not in merged:
|
||||
merged[uid] = {"name": uid, "rcv": 0, "cpl": 0, "rcd": 0}
|
||||
r, c = op_map.get(uid, (0, 0))
|
||||
merged[uid]["rcv"] = r
|
||||
merged[uid]["cpl"] = c
|
||||
merged[uid]["rcd"] = record_map.get(uid, 0)
|
||||
|
||||
# ── 4. 组装 + 排序(总次数降序,无操作的排在最后)──
|
||||
# ── 5. 组装 + 排序(总次数降序,无操作的排在最后)──
|
||||
items: list[UserOperation] = []
|
||||
for uid, v in merged.items():
|
||||
items.append(UserOperation(
|
||||
|
||||
@ -1049,16 +1049,6 @@ async def add_task_record(
|
||||
db.add(record)
|
||||
await db.flush()
|
||||
|
||||
# 🔧 操作日志:记录一次「上传备注」操作(供人员操作统计)
|
||||
if current_user:
|
||||
from app.models.task_log import TaskLog
|
||||
db.add(TaskLog(
|
||||
task_id=task_id,
|
||||
operator_id=current_user.get("username") or current_user.get("sub") or "",
|
||||
action_type="record",
|
||||
remark=f"上传备注: {(data.remark or '')[:100]}",
|
||||
))
|
||||
|
||||
# 🚀 留言通知:给任务当前负责人发送提醒(不给自己发)
|
||||
if (
|
||||
current_user
|
||||
|
||||
Reference in New Issue
Block a user