Ver Fonte

feat(oa): expose instance comment APIs and embed comments in detail

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu há 1 mês atrás
pai
commit
55e1306eba
2 ficheiros alterados com 118 adições e 2 exclusões
  1. 107 1
      backend/app/api/oa_approval.py
  2. 11 1
      backend/app/services/oa_engine.py

+ 107 - 1
backend/app/api/oa_approval.py

@@ -764,6 +764,14 @@ class OaTransferBody(BaseModel):
     comment: Optional[str] = None
 
 
+class OaCommentCreateBody(BaseModel):
+    model_config = ConfigDict(populate_by_name=True)
+    content: str
+    attachment_refs: Optional[List[Dict[str, Any]]] = Field(
+        None, alias="attachmentRefs"
+    )
+
+
 class OaResubmitBody(BaseModel):
     model_config = ConfigDict(populate_by_name=True)
     form_data: Optional[Dict[str, Any]] = Field(None, alias="formData")
@@ -988,7 +996,105 @@ async def get_oa_instance(
 
     try:
         tenant_no = _get_tenant_no(db, user)
-        return success_response(get_instance_detail(db, instance_id, tenant_no=tenant_no))
+        return success_response(
+            get_instance_detail(
+                db,
+                instance_id,
+                tenant_no=tenant_no,
+                viewer_user_id=user.get("user_id") or "",
+            )
+        )
+    except OaEngineError as e:
+        return error_response(400, str(e))
+
+
+@router.get("/instances/{instance_id}/form-attachments")
+async def list_oa_instance_form_attachments(
+    instance_id: str,
+    user: dict = Depends(require_admin_or_super_admin),
+    db: Session = Depends(get_db),
+):
+    from app.services import oa_instance_comment as oa_comment
+    from app.services.oa_engine import OaEngineError
+
+    try:
+        tenant_no = _get_tenant_no(db, user)
+        items = oa_comment.list_form_attachments(
+            db, instance_id=instance_id, tenant_no=tenant_no
+        )
+        return success_response({"items": items})
+    except OaEngineError as e:
+        return error_response(400, str(e))
+
+
+@router.get("/instances/{instance_id}/comments")
+async def list_oa_instance_comments(
+    instance_id: str,
+    user: dict = Depends(require_admin_or_super_admin),
+    db: Session = Depends(get_db),
+):
+    from app.services import oa_instance_comment as oa_comment
+    from app.services.oa_engine import OaEngineError
+
+    try:
+        tenant_no = _get_tenant_no(db, user)
+        items = oa_comment.list_comments(
+            db,
+            instance_id=instance_id,
+            tenant_no=tenant_no,
+            viewer_user_id=user.get("user_id") or "",
+        )
+        return success_response({"list": items})
+    except OaEngineError as e:
+        return error_response(400, str(e))
+
+
+@router.post("/instances/{instance_id}/comments")
+async def create_oa_instance_comment(
+    instance_id: str,
+    body: OaCommentCreateBody,
+    user: dict = Depends(require_admin_or_super_admin),
+    db: Session = Depends(get_db),
+):
+    from app.services import oa_instance_comment as oa_comment
+    from app.services.oa_engine import OaEngineError
+
+    try:
+        tenant_no = _get_tenant_no(db, user)
+        data = oa_comment.create_comment(
+            db,
+            instance_id=instance_id,
+            tenant_no=tenant_no,
+            user_id=user.get("user_id") or "",
+            dept_id=user.get("dept_id") or "",
+            content=body.content,
+            attachment_refs=body.attachment_refs,
+        )
+        return success_response(data)
+    except OaEngineError as e:
+        return error_response(400, str(e))
+
+
+@router.post("/instances/{instance_id}/comments/{comment_id}/revoke")
+async def revoke_oa_instance_comment(
+    instance_id: str,
+    comment_id: str,
+    user: dict = Depends(require_admin_or_super_admin),
+    db: Session = Depends(get_db),
+):
+    from app.services import oa_instance_comment as oa_comment
+    from app.services.oa_engine import OaEngineError
+
+    try:
+        tenant_no = _get_tenant_no(db, user)
+        data = oa_comment.revoke_comment(
+            db,
+            instance_id=instance_id,
+            comment_id=comment_id,
+            tenant_no=tenant_no,
+            user_id=user.get("user_id") or "",
+        )
+        return success_response(data)
     except OaEngineError as e:
         return error_response(400, str(e))
 

+ 11 - 1
backend/app/services/oa_engine.py

@@ -1976,7 +1976,9 @@ def _get_instance(db: Session, instance_id: str, tenant_no: str) -> OaInstance:
     return inst
 
 
-def get_instance_detail(db: Session, instance_id: str, *, tenant_no: str) -> Dict[str, Any]:
+def get_instance_detail(
+    db: Session, instance_id: str, *, tenant_no: str, viewer_user_id: str = ""
+) -> Dict[str, Any]:
     inst = _get_instance(db, instance_id, tenant_no)
     app = oa_crud.get_app(db, inst.app_id, tenant_no)
     ver = (
@@ -2042,6 +2044,14 @@ def get_instance_detail(db: Session, instance_id: str, *, tenant_no: str) -> Dic
     # 不再暴露旧单/重提单关联跳转
     data["sourceInstanceId"] = ""
     data["resubmittedInstanceId"] = ""
+    from app.services import oa_instance_comment as oa_comment
+
+    data["comments"] = oa_comment.list_comments(
+        db,
+        instance_id=instance_id,
+        tenant_no=tenant_no,
+        viewer_user_id=viewer_user_id or "",
+    )
     return data