feat(oa): auto-pass approval when assignee is initiator
Extract approve core and hook after creating approval tasks when the advanced setting is enabled. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
d69388573a
commit
8bd45561b7
1 file changed
+130
-54
@@ -30,6 +30,9 @@ class OaEngineError(ValueError):
|
||||
"""引擎业务错误"""
|
||||
|
||||
|
||||
_AUTO_PASS_COMMENT = "系统自动通过"
|
||||
|
||||
|
||||
def _loads(text: Optional[str], default: Any = None) -> Any:
|
||||
if text is None or text == "":
|
||||
return default
|
||||
@@ -1501,6 +1504,13 @@ def advance_from(
|
||||
continue
|
||||
if not tasks:
|
||||
raise OaEngineError("审批节点未生成任务")
|
||||
_maybe_auto_pass_initiator(
|
||||
db,
|
||||
inst=inst,
|
||||
ver=ver,
|
||||
tasks=tasks,
|
||||
user_id=user_id,
|
||||
)
|
||||
return
|
||||
# 未知类型跳过子节点
|
||||
cur = next_node(cur)
|
||||
@@ -1773,6 +1783,116 @@ def list_tasks(
|
||||
return _enrich_list_rows(db, tenant_no=tenant_no, rows=rows, instances=insts)
|
||||
|
||||
|
||||
def _approve_task_core(
|
||||
db: Session,
|
||||
*,
|
||||
task: OaTask,
|
||||
inst: OaInstance,
|
||||
ver: OaAppVersion,
|
||||
user_id: str,
|
||||
comment: Optional[str],
|
||||
) -> bool:
|
||||
"""将 pending 审批任务置为 approved 并按或签/会签决定是否推进。
|
||||
|
||||
返回 True 表示已调用 advance_from 推进;False 表示会签未齐、未推进。
|
||||
调用方负责 commit(若需要)。
|
||||
"""
|
||||
now = datetime.now()
|
||||
task.comment_text = (comment or "").strip() or None
|
||||
task.status = "approved"
|
||||
task.update_by = user_id
|
||||
task.update_time = now
|
||||
db.add(task)
|
||||
# Session 默认 autoflush=False:不先 flush 时,后续按 status=pending 的查询仍会命中本任务,
|
||||
# 或签「取消同节点其余待办」会把本人已同意覆盖成 done。
|
||||
db.flush()
|
||||
|
||||
sign_mode = (task.sign_mode or "or").strip() or "or"
|
||||
pending_same = (
|
||||
db.query(OaTask)
|
||||
.filter(
|
||||
OaTask.instance_id == inst.id,
|
||||
OaTask.node_key == task.node_key,
|
||||
OaTask.task_type == "approval",
|
||||
OaTask.id != task.id,
|
||||
OaTask.status == "pending",
|
||||
OaTask.del_flag == 0,
|
||||
)
|
||||
.count()
|
||||
)
|
||||
if sign_mode == "and" and pending_same > 0:
|
||||
return False
|
||||
|
||||
if sign_mode != "and":
|
||||
for s in (
|
||||
db.query(OaTask)
|
||||
.filter(
|
||||
OaTask.instance_id == inst.id,
|
||||
OaTask.node_key == task.node_key,
|
||||
OaTask.id != task.id,
|
||||
OaTask.status == "pending",
|
||||
OaTask.del_flag == 0,
|
||||
)
|
||||
.all()
|
||||
):
|
||||
s.status = "done"
|
||||
s.update_by = user_id
|
||||
s.update_time = now
|
||||
db.add(s)
|
||||
|
||||
root = _flow_root(_loads(ver.flow_tree_json, {}))
|
||||
node = _find_node(root, task.node_key or "")
|
||||
if not node:
|
||||
raise OaEngineError("找不到对应流程节点")
|
||||
advance_from(
|
||||
db,
|
||||
inst=inst,
|
||||
ver=ver,
|
||||
from_node=node,
|
||||
user_id=user_id,
|
||||
initiator_select_by_node=_load_initiator_select_by_node(inst),
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def _maybe_auto_pass_initiator(
|
||||
db: Session,
|
||||
*,
|
||||
inst: OaInstance,
|
||||
ver: OaAppVersion,
|
||||
tasks: List[OaTask],
|
||||
user_id: Optional[str],
|
||||
) -> None:
|
||||
_ = user_id
|
||||
advanced = _advanced(ver)
|
||||
if not advanced.get("autoPassWhenApproverIsInitiator"):
|
||||
return
|
||||
if inst.status != "running":
|
||||
return
|
||||
initiator = (inst.initiator_user_id or "").strip()
|
||||
if not initiator:
|
||||
return
|
||||
self_task = None
|
||||
for t in tasks:
|
||||
if (
|
||||
t.task_type == "approval"
|
||||
and t.status == "pending"
|
||||
and (t.assignee_user_id or "") == initiator
|
||||
):
|
||||
self_task = t
|
||||
break
|
||||
if not self_task:
|
||||
return
|
||||
_approve_task_core(
|
||||
db,
|
||||
task=self_task,
|
||||
inst=inst,
|
||||
ver=ver,
|
||||
user_id=initiator,
|
||||
comment=_AUTO_PASS_COMMENT,
|
||||
)
|
||||
|
||||
|
||||
def complete_task(
|
||||
db: Session,
|
||||
task_id: str,
|
||||
@@ -1814,18 +1934,14 @@ def complete_task(
|
||||
if advanced.get("commentRequired") and not (comment or "").strip():
|
||||
raise OaEngineError("请填写审批意见")
|
||||
|
||||
now = datetime.now()
|
||||
task.comment_text = (comment or "").strip() or None
|
||||
task.status = "approved" if action == "approve" else "rejected"
|
||||
task.update_by = user_id
|
||||
task.update_time = now
|
||||
db.add(task)
|
||||
# Session 默认 autoflush=False:不先 flush 时,后续按 status=pending 的查询仍会命中本任务,
|
||||
# 或签「取消同节点其余待办」会把本人已同意/已拒绝覆盖成 done,导致「已处理」列表查不到。
|
||||
db.flush()
|
||||
|
||||
if action == "reject":
|
||||
# 同节点其他待办作废(排除当前任务)
|
||||
now = datetime.now()
|
||||
task.comment_text = (comment or "").strip() or None
|
||||
task.status = "rejected"
|
||||
task.update_by = user_id
|
||||
task.update_time = now
|
||||
db.add(task)
|
||||
db.flush()
|
||||
siblings = (
|
||||
db.query(OaTask)
|
||||
.filter(
|
||||
@@ -1849,53 +1965,13 @@ def complete_task(
|
||||
db.commit()
|
||||
return get_instance_detail(db, inst.id, tenant_no=tenant_no)
|
||||
|
||||
# 或签:一人通过即可;会签:全部通过
|
||||
sign_mode = (task.sign_mode or "or").strip() or "or"
|
||||
pending_same = (
|
||||
db.query(OaTask)
|
||||
.filter(
|
||||
OaTask.instance_id == inst.id,
|
||||
OaTask.node_key == task.node_key,
|
||||
OaTask.task_type == "approval",
|
||||
OaTask.id != task.id,
|
||||
OaTask.status == "pending",
|
||||
OaTask.del_flag == 0,
|
||||
)
|
||||
.count()
|
||||
)
|
||||
if sign_mode == "and" and pending_same > 0:
|
||||
db.commit()
|
||||
return get_instance_detail(db, inst.id, tenant_no=tenant_no)
|
||||
|
||||
# 或签:取消同节点其余待办(排除当前任务)
|
||||
if sign_mode != "and":
|
||||
for s in (
|
||||
db.query(OaTask)
|
||||
.filter(
|
||||
OaTask.instance_id == inst.id,
|
||||
OaTask.node_key == task.node_key,
|
||||
OaTask.id != task.id,
|
||||
OaTask.status == "pending",
|
||||
OaTask.del_flag == 0,
|
||||
)
|
||||
.all()
|
||||
):
|
||||
s.status = "done"
|
||||
s.update_by = user_id
|
||||
s.update_time = now
|
||||
db.add(s)
|
||||
|
||||
root = _flow_root(_loads(ver.flow_tree_json, {}))
|
||||
node = _find_node(root, task.node_key or "")
|
||||
if not node:
|
||||
raise OaEngineError("找不到对应流程节点")
|
||||
advance_from(
|
||||
_approve_task_core(
|
||||
db,
|
||||
task=task,
|
||||
inst=inst,
|
||||
ver=ver,
|
||||
from_node=node,
|
||||
user_id=user_id,
|
||||
initiator_select_by_node=_load_initiator_select_by_node(inst),
|
||||
comment=comment,
|
||||
)
|
||||
db.commit()
|
||||
return get_instance_detail(db, inst.id, tenant_no=tenant_no)
|
||||
|
||||
Reference in new issue
Block a user