|
|
@@ -108,3 +108,183 @@ def normalize_attachment_refs(
|
|
|
}
|
|
|
)
|
|
|
return out
|
|
|
+
|
|
|
+
|
|
|
+def _fmt_time(dt: Optional[datetime]) -> str:
|
|
|
+ return dt.strftime("%Y-%m-%d %H:%M:%S") if dt else ""
|
|
|
+
|
|
|
+
|
|
|
+def _comment_to_dict(
|
|
|
+ row: OaInstanceComment,
|
|
|
+ *,
|
|
|
+ name_map: Dict[str, str],
|
|
|
+ viewer_user_id: str,
|
|
|
+ instance_status: str,
|
|
|
+) -> Dict[str, Any]:
|
|
|
+ refs = _loads(row.attachment_refs_json, [])
|
|
|
+ if not isinstance(refs, list):
|
|
|
+ refs = []
|
|
|
+ status = (row.status or "normal").strip() or "normal"
|
|
|
+ can_revoke = (
|
|
|
+ status == "normal"
|
|
|
+ and instance_status == "running"
|
|
|
+ and (row.create_by or "") == (viewer_user_id or "")
|
|
|
+ )
|
|
|
+ return {
|
|
|
+ "id": row.id,
|
|
|
+ "instanceId": row.instance_id,
|
|
|
+ "content": row.content or "",
|
|
|
+ "attachmentRefs": refs,
|
|
|
+ "status": status,
|
|
|
+ "revokedTime": _fmt_time(row.revoked_time),
|
|
|
+ "createBy": row.create_by or "",
|
|
|
+ "createByName": name_map.get(row.create_by or "", row.create_by or ""),
|
|
|
+ "createTime": _fmt_time(row.create_time),
|
|
|
+ "canRevoke": can_revoke,
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+def _load_version_schema(db: Session, inst: OaInstance) -> Any:
|
|
|
+ ver = (
|
|
|
+ db.query(OaAppVersion)
|
|
|
+ .filter(OaAppVersion.id == inst.app_version_id, OaAppVersion.del_flag == 0)
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not ver:
|
|
|
+ return {}
|
|
|
+ return _loads(ver.form_schema_json, {})
|
|
|
+
|
|
|
+
|
|
|
+def list_comments(
|
|
|
+ db: Session,
|
|
|
+ *,
|
|
|
+ instance_id: str,
|
|
|
+ tenant_no: str,
|
|
|
+ viewer_user_id: str,
|
|
|
+) -> List[Dict[str, Any]]:
|
|
|
+ inst = _get_instance(db, instance_id, tenant_no)
|
|
|
+ rows = (
|
|
|
+ db.query(OaInstanceComment)
|
|
|
+ .filter(
|
|
|
+ OaInstanceComment.instance_id == instance_id,
|
|
|
+ OaInstanceComment.tenant_no == tenant_no,
|
|
|
+ OaInstanceComment.del_flag == 0,
|
|
|
+ )
|
|
|
+ .order_by(OaInstanceComment.create_time.asc())
|
|
|
+ .all()
|
|
|
+ )
|
|
|
+ name_map = _user_name_map(db, [r.create_by for r in rows if r.create_by])
|
|
|
+ return [
|
|
|
+ _comment_to_dict(
|
|
|
+ r,
|
|
|
+ name_map=name_map,
|
|
|
+ viewer_user_id=viewer_user_id,
|
|
|
+ instance_status=inst.status or "",
|
|
|
+ )
|
|
|
+ for r in rows
|
|
|
+ ]
|
|
|
+
|
|
|
+
|
|
|
+def list_form_attachments(
|
|
|
+ db: Session, *, instance_id: str, tenant_no: str
|
|
|
+) -> List[Dict[str, Any]]:
|
|
|
+ inst = _get_instance(db, instance_id, tenant_no)
|
|
|
+ schema = _load_version_schema(db, inst)
|
|
|
+ form = _loads(inst.form_data_json, {})
|
|
|
+ if not isinstance(form, dict):
|
|
|
+ form = {}
|
|
|
+ return enumerate_form_attachments(schema, form)
|
|
|
+
|
|
|
+
|
|
|
+def create_comment(
|
|
|
+ db: Session,
|
|
|
+ *,
|
|
|
+ instance_id: str,
|
|
|
+ tenant_no: str,
|
|
|
+ user_id: str,
|
|
|
+ dept_id: str,
|
|
|
+ content: str,
|
|
|
+ attachment_refs: Optional[List[Dict[str, Any]]],
|
|
|
+) -> Dict[str, Any]:
|
|
|
+ inst = _get_instance(db, instance_id, tenant_no)
|
|
|
+ if (inst.status or "") != "running":
|
|
|
+ raise OaEngineError("仅审批进行中可评论")
|
|
|
+ text = (content or "").strip()
|
|
|
+ if not text:
|
|
|
+ raise OaEngineError("评论内容不能为空")
|
|
|
+ if len(text) > CONTENT_MAX:
|
|
|
+ raise OaEngineError(f"评论内容不能超过{CONTENT_MAX}字")
|
|
|
+ schema = _load_version_schema(db, inst)
|
|
|
+ form = _loads(inst.form_data_json, {})
|
|
|
+ if not isinstance(form, dict):
|
|
|
+ form = {}
|
|
|
+ refs = normalize_attachment_refs(schema, form, attachment_refs)
|
|
|
+ now = datetime.now()
|
|
|
+ row = OaInstanceComment(
|
|
|
+ id=generate_uuid(),
|
|
|
+ instance_id=instance_id,
|
|
|
+ content=text,
|
|
|
+ attachment_refs_json=json.dumps(refs, ensure_ascii=False) if refs else None,
|
|
|
+ status="normal",
|
|
|
+ revoked_time=None,
|
|
|
+ tenant_no=tenant_no,
|
|
|
+ create_by=user_id,
|
|
|
+ create_dept_id=dept_id or "",
|
|
|
+ create_time=now,
|
|
|
+ update_by=user_id,
|
|
|
+ update_time=now,
|
|
|
+ del_flag=0,
|
|
|
+ )
|
|
|
+ db.add(row)
|
|
|
+ db.commit()
|
|
|
+ db.refresh(row)
|
|
|
+ name_map = _user_name_map(db, [user_id])
|
|
|
+ return _comment_to_dict(
|
|
|
+ row,
|
|
|
+ name_map=name_map,
|
|
|
+ viewer_user_id=user_id,
|
|
|
+ instance_status=inst.status or "",
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+def revoke_comment(
|
|
|
+ db: Session,
|
|
|
+ *,
|
|
|
+ instance_id: str,
|
|
|
+ comment_id: str,
|
|
|
+ tenant_no: str,
|
|
|
+ user_id: str,
|
|
|
+) -> Dict[str, Any]:
|
|
|
+ inst = _get_instance(db, instance_id, tenant_no)
|
|
|
+ if (inst.status or "") != "running":
|
|
|
+ raise OaEngineError("仅审批进行中可撤回评论")
|
|
|
+ row = (
|
|
|
+ db.query(OaInstanceComment)
|
|
|
+ .filter(
|
|
|
+ OaInstanceComment.id == comment_id,
|
|
|
+ OaInstanceComment.instance_id == instance_id,
|
|
|
+ OaInstanceComment.tenant_no == tenant_no,
|
|
|
+ OaInstanceComment.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not row:
|
|
|
+ raise OaEngineError("评论不存在")
|
|
|
+ if (row.create_by or "") != (user_id or ""):
|
|
|
+ raise OaEngineError("只能撤回自己的评论")
|
|
|
+ now = datetime.now()
|
|
|
+ if (row.status or "") != "revoked":
|
|
|
+ row.status = "revoked"
|
|
|
+ row.revoked_time = now
|
|
|
+ row.update_by = user_id
|
|
|
+ row.update_time = now
|
|
|
+ db.add(row)
|
|
|
+ db.commit()
|
|
|
+ db.refresh(row)
|
|
|
+ name_map = _user_name_map(db, [row.create_by] if row.create_by else [])
|
|
|
+ return _comment_to_dict(
|
|
|
+ row,
|
|
|
+ name_map=name_map,
|
|
|
+ viewer_user_id=user_id,
|
|
|
+ instance_status=inst.status or "",
|
|
|
+ )
|