|
|
@@ -829,6 +829,12 @@ def _task_to_dict(t: OaTask, *, assignee_user_name: str = "") -> Dict[str, Any]:
|
|
|
"commentText": t.comment_text or "",
|
|
|
"resolveSource": t.resolve_source or "",
|
|
|
"signMode": t.sign_mode or "",
|
|
|
+ "isRead": bool(int(getattr(t, "is_read", 0) or 0)),
|
|
|
+ "readTime": (
|
|
|
+ t.read_time.strftime("%Y-%m-%d %H:%M:%S")
|
|
|
+ if getattr(t, "read_time", None)
|
|
|
+ else ""
|
|
|
+ ),
|
|
|
"createTime": t.create_time.strftime("%Y-%m-%d %H:%M:%S") if t.create_time else "",
|
|
|
"updateTime": t.update_time.strftime("%Y-%m-%d %H:%M:%S") if t.update_time else "",
|
|
|
}
|
|
|
@@ -1479,6 +1485,8 @@ def _create_tasks_for_node(
|
|
|
comment_text=None,
|
|
|
resolve_source=resolve_source,
|
|
|
sign_mode=sign_mode if task_type == "approval" else None,
|
|
|
+ is_read=0,
|
|
|
+ read_time=None,
|
|
|
round_no=int(getattr(inst, "current_round", None) or 1),
|
|
|
tenant_no=inst.tenant_no,
|
|
|
order_num=seq,
|
|
|
@@ -1928,12 +1936,99 @@ def get_instance_detail(db: Session, instance_id: str, *, tenant_no: str) -> Dic
|
|
|
return data
|
|
|
|
|
|
|
|
|
+def _normalize_cc_read_status(raw: Optional[str]) -> str:
|
|
|
+ v = (raw or "").strip().lower() or "unread"
|
|
|
+ if v not in ("unread", "read", "all"):
|
|
|
+ raise OaEngineError("readStatus 仅支持 unread、read、all")
|
|
|
+ return v
|
|
|
+
|
|
|
+
|
|
|
+def _apply_cc_task_read(
|
|
|
+ db: Session,
|
|
|
+ *,
|
|
|
+ task: OaTask,
|
|
|
+ user_id: str,
|
|
|
+ now: datetime,
|
|
|
+) -> bool:
|
|
|
+ """将抄送任务标为已读。返回是否发生了写入。幂等时返回 False。"""
|
|
|
+ if int(getattr(task, "is_read", 0) or 0) == 1:
|
|
|
+ return False
|
|
|
+ task.is_read = 1
|
|
|
+ task.read_time = now
|
|
|
+ task.update_by = user_id
|
|
|
+ task.update_time = now
|
|
|
+ db.add(task)
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+def count_cc_unread(db: Session, *, tenant_no: str, user_id: str) -> int:
|
|
|
+ return (
|
|
|
+ db.query(OaTask)
|
|
|
+ .filter(
|
|
|
+ OaTask.tenant_no == tenant_no,
|
|
|
+ OaTask.del_flag == 0,
|
|
|
+ OaTask.assignee_user_id == user_id,
|
|
|
+ OaTask.task_type == "cc",
|
|
|
+ OaTask.is_read == 0,
|
|
|
+ )
|
|
|
+ .count()
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+def mark_cc_task_read(
|
|
|
+ db: Session, *, tenant_no: str, user_id: str, task_id: str
|
|
|
+) -> Dict[str, Any]:
|
|
|
+ task = (
|
|
|
+ db.query(OaTask)
|
|
|
+ .filter(
|
|
|
+ OaTask.id == task_id,
|
|
|
+ OaTask.tenant_no == tenant_no,
|
|
|
+ OaTask.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not task or task.task_type != "cc" or task.assignee_user_id != user_id:
|
|
|
+ raise OaEngineError("抄送任务不存在或无权操作")
|
|
|
+ now = datetime.now()
|
|
|
+ _apply_cc_task_read(db, task=task, user_id=user_id, now=now)
|
|
|
+ db.commit()
|
|
|
+ db.refresh(task)
|
|
|
+ return _task_to_dict(task)
|
|
|
+
|
|
|
+
|
|
|
+def mark_cc_tasks_read_batch(
|
|
|
+ db: Session, *, tenant_no: str, user_id: str, ids: List[str]
|
|
|
+) -> Dict[str, Any]:
|
|
|
+ id_list = [x.strip() for x in (ids or []) if (x or "").strip()]
|
|
|
+ if not id_list:
|
|
|
+ return {"updated": 0}
|
|
|
+ rows = (
|
|
|
+ db.query(OaTask)
|
|
|
+ .filter(
|
|
|
+ OaTask.tenant_no == tenant_no,
|
|
|
+ OaTask.del_flag == 0,
|
|
|
+ OaTask.assignee_user_id == user_id,
|
|
|
+ OaTask.task_type == "cc",
|
|
|
+ OaTask.id.in_(id_list),
|
|
|
+ )
|
|
|
+ .all()
|
|
|
+ )
|
|
|
+ now = datetime.now()
|
|
|
+ updated = 0
|
|
|
+ for t in rows:
|
|
|
+ if _apply_cc_task_read(db, task=t, user_id=user_id, now=now):
|
|
|
+ updated += 1
|
|
|
+ db.commit()
|
|
|
+ return {"updated": updated}
|
|
|
+
|
|
|
+
|
|
|
def list_tasks(
|
|
|
db: Session,
|
|
|
*,
|
|
|
tenant_no: str,
|
|
|
user_id: str,
|
|
|
kind: str,
|
|
|
+ read_status: Optional[str] = None,
|
|
|
) -> List[Dict[str, Any]]:
|
|
|
kind = (kind or "").strip()
|
|
|
if kind == "pending":
|
|
|
@@ -1959,6 +2054,12 @@ def list_tasks(
|
|
|
OaTask.assignee_user_id == user_id,
|
|
|
OaTask.task_type == "cc",
|
|
|
)
|
|
|
+ rs = _normalize_cc_read_status(read_status)
|
|
|
+ if rs == "unread":
|
|
|
+ q = q.filter(OaTask.is_read == 0)
|
|
|
+ elif rs == "read":
|
|
|
+ q = q.filter(OaTask.is_read == 1)
|
|
|
+ # all: 不加 is_read 条件
|
|
|
elif kind == "mine":
|
|
|
insts = (
|
|
|
db.query(OaInstance)
|