Align with DingTalk semantics: reject ends the instance, return keeps it for initiator edits, and revoke-and-resubmit creates a linked new instance. Progress timeline projects rounds via oa_instance_event. Co-authored-by: Cursor <cursoragent@cursor.com>
746 lines
24 KiB
Python
746 lines
24 KiB
Python
"""OA 审批管理接口(钉钉交互)"""
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.database import get_db
|
|
from app.core.menu_guard import require_admin_or_super_admin
|
|
from app.core.response import error_response, success_response
|
|
from app.crud import oa_approval as oa_crud
|
|
from app.models.models import SysUser
|
|
|
|
router = APIRouter(prefix="/web/admin/oa-approval", tags=["OA审批"])
|
|
|
|
|
|
def _get_tenant_no(db: Session, user: dict) -> str:
|
|
tenant = (user.get("tenant_no") or "").strip()
|
|
if tenant:
|
|
return tenant
|
|
uid = user.get("user_id")
|
|
if uid:
|
|
row = db.query(SysUser).filter(SysUser.id == uid, SysUser.del_flag == 0).first()
|
|
if row and row.tenant_no:
|
|
return row.tenant_no
|
|
return "zkxw"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 工作流角色
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class OaRoleCreateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
role_name: str = Field(..., alias="roleName")
|
|
role_code: str = Field(..., alias="roleCode")
|
|
status: Optional[str] = Field("1")
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class OaRoleUpdateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
role_name: Optional[str] = Field(None, alias="roleName")
|
|
status: Optional[str] = None
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class OaRoleUsersBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
user_ids: List[str] = Field(default_factory=list, alias="userIds")
|
|
|
|
|
|
@router.get("/roles")
|
|
async def list_oa_roles(
|
|
keyword: Optional[str] = None,
|
|
status: Optional[str] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _get_tenant_no(db, user)
|
|
items = oa_crud.list_roles(db, tenant_no=tenant_no, keyword=keyword, status=status)
|
|
return success_response({"list": items})
|
|
|
|
|
|
@router.post("/roles/ensure-presets")
|
|
async def ensure_oa_role_presets(
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _get_tenant_no(db, user)
|
|
created = oa_crud.ensure_presets(db, tenant_no, user_id=user.get("user_id"))
|
|
return success_response(
|
|
{"createdCount": len(created)},
|
|
message="预置角色已就绪",
|
|
)
|
|
|
|
|
|
@router.post("/roles")
|
|
async def create_oa_role(
|
|
body: OaRoleCreateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
obj = oa_crud.create_role(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
role_name=body.role_name,
|
|
role_code=body.role_code,
|
|
status=body.status or "1",
|
|
order_num=body.order_num,
|
|
remark=body.remark,
|
|
user_id=user.get("user_id"),
|
|
)
|
|
return success_response(oa_crud._role_to_dict(obj), message="创建成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.put("/roles/{role_id}")
|
|
async def update_oa_role(
|
|
role_id: str,
|
|
body: OaRoleUpdateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
payload: dict[str, Any] = body.model_dump(exclude_unset=True, by_alias=False)
|
|
obj = oa_crud.update_role(
|
|
db,
|
|
role_id,
|
|
tenant_no=tenant_no,
|
|
role_name=payload.get("role_name"),
|
|
status=payload.get("status"),
|
|
order_num=payload.get("order_num"),
|
|
remark=payload.get("remark"),
|
|
user_id=user.get("user_id"),
|
|
)
|
|
return success_response(oa_crud._role_to_dict(obj), message="更新成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.delete("/roles/{role_id}")
|
|
async def delete_oa_role(
|
|
role_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
oa_crud.delete_role(db, role_id, tenant_no=tenant_no, user_id=user.get("user_id"))
|
|
return success_response(None, message="删除成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.get("/roles/{role_id}/users")
|
|
async def list_oa_role_users(
|
|
role_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _get_tenant_no(db, user)
|
|
if not oa_crud.get_role(db, role_id, tenant_no):
|
|
return error_response(404, "角色不存在")
|
|
return success_response({"list": oa_crud.list_role_users(db, role_id, tenant_no)})
|
|
|
|
|
|
@router.put("/roles/{role_id}/users")
|
|
async def replace_oa_role_users(
|
|
role_id: str,
|
|
body: OaRoleUsersBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
oa_crud.replace_role_users(
|
|
db,
|
|
role_id,
|
|
tenant_no=tenant_no,
|
|
user_ids=body.user_ids,
|
|
operator_id=user.get("user_id"),
|
|
)
|
|
return success_response(
|
|
{"list": oa_crud.list_role_users(db, role_id, tenant_no)},
|
|
message="成员已更新",
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 分组
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class OaGroupCreateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
group_name: str = Field(..., alias="groupName")
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class OaGroupUpdateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
group_name: Optional[str] = Field(None, alias="groupName")
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
@router.get("/groups")
|
|
async def list_oa_groups(
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _get_tenant_no(db, user)
|
|
return success_response({"list": oa_crud.list_groups(db, tenant_no=tenant_no)})
|
|
|
|
|
|
@router.post("/groups")
|
|
async def create_oa_group(
|
|
body: OaGroupCreateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
obj = oa_crud.create_group(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
group_name=body.group_name,
|
|
order_num=body.order_num,
|
|
remark=body.remark,
|
|
user_id=user.get("user_id"),
|
|
)
|
|
return success_response(oa_crud._group_to_dict(obj), message="创建成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.put("/groups/{group_id}")
|
|
async def update_oa_group(
|
|
group_id: str,
|
|
body: OaGroupUpdateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
payload = body.model_dump(exclude_unset=True, by_alias=False)
|
|
obj = oa_crud.update_group(
|
|
db,
|
|
group_id,
|
|
tenant_no=tenant_no,
|
|
group_name=payload.get("group_name"),
|
|
order_num=payload.get("order_num"),
|
|
remark=payload.get("remark"),
|
|
user_id=user.get("user_id"),
|
|
)
|
|
return success_response(oa_crud._group_to_dict(obj), message="更新成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.delete("/groups/{group_id}")
|
|
async def delete_oa_group(
|
|
group_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
oa_crud.delete_group(db, group_id, tenant_no=tenant_no, user_id=user.get("user_id"))
|
|
return success_response(None, message="删除成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 应用 / 草稿
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class OaAppCreateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
app_name: str = Field(..., alias="appName")
|
|
group_id: Optional[str] = Field(None, alias="groupId")
|
|
icon_url: Optional[str] = Field(None, alias="iconUrl")
|
|
description: Optional[str] = None
|
|
initiator_scope: Optional[str] = Field("all", alias="initiatorScope")
|
|
initiator_user_ids: Optional[List[str]] = Field(None, alias="initiatorUserIds")
|
|
admin_scope: Optional[str] = Field("all_oa_admin", alias="adminScope")
|
|
admin_user_ids: Optional[List[str]] = Field(None, alias="adminUserIds")
|
|
status: Optional[str] = "1"
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class OaAppUpdateBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
app_name: Optional[str] = Field(None, alias="appName")
|
|
group_id: Optional[str] = Field(None, alias="groupId")
|
|
icon_url: Optional[str] = Field(None, alias="iconUrl")
|
|
description: Optional[str] = None
|
|
initiator_scope: Optional[str] = Field(None, alias="initiatorScope")
|
|
initiator_user_ids: Optional[List[str]] = Field(None, alias="initiatorUserIds")
|
|
admin_scope: Optional[str] = Field(None, alias="adminScope")
|
|
admin_user_ids: Optional[List[str]] = Field(None, alias="adminUserIds")
|
|
status: Optional[str] = None
|
|
order_num: Optional[int] = Field(None, alias="orderNum")
|
|
remark: Optional[str] = None
|
|
|
|
|
|
class OaDraftSaveBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
basic: Optional[Dict[str, Any]] = None
|
|
form_schema_json: Optional[Any] = Field(None, alias="formSchemaJson")
|
|
flow_tree_json: Optional[Any] = Field(None, alias="flowTreeJson")
|
|
advanced_settings_json: Optional[Any] = Field(None, alias="advancedSettingsJson")
|
|
|
|
|
|
@router.get("/apps")
|
|
async def list_oa_apps(
|
|
groupId: Optional[str] = None,
|
|
keyword: Optional[str] = None,
|
|
status: Optional[str] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _get_tenant_no(db, user)
|
|
items = oa_crud.list_apps(
|
|
db, tenant_no=tenant_no, group_id=groupId, keyword=keyword, status=status
|
|
)
|
|
return success_response({"list": items})
|
|
|
|
|
|
@router.post("/apps")
|
|
async def create_oa_app(
|
|
body: OaAppCreateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
obj = oa_crud.create_app(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
app_name=body.app_name,
|
|
group_id=body.group_id,
|
|
icon_url=body.icon_url,
|
|
description=body.description,
|
|
initiator_scope=body.initiator_scope or "all",
|
|
initiator_user_ids=body.initiator_user_ids,
|
|
admin_scope=body.admin_scope or "all_oa_admin",
|
|
admin_user_ids=body.admin_user_ids,
|
|
status=body.status or "1",
|
|
order_num=body.order_num,
|
|
remark=body.remark,
|
|
user_id=user.get("user_id"),
|
|
)
|
|
group_name = ""
|
|
if obj.group_id:
|
|
g = oa_crud.get_group(db, obj.group_id, tenant_no)
|
|
group_name = g.group_name if g else ""
|
|
return success_response(
|
|
oa_crud._app_to_dict(obj, group_name=group_name, has_draft=True),
|
|
message="创建成功",
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.put("/apps/{app_id}")
|
|
async def update_oa_app(
|
|
app_id: str,
|
|
body: OaAppUpdateBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
payload = body.model_dump(exclude_unset=True, by_alias=False)
|
|
obj = oa_crud.update_app(db, app_id, tenant_no=tenant_no, user_id=user.get("user_id"), **payload)
|
|
group_name = ""
|
|
if obj.group_id:
|
|
g = oa_crud.get_group(db, obj.group_id, tenant_no)
|
|
group_name = g.group_name if g else ""
|
|
return success_response(oa_crud._app_to_dict(obj, group_name=group_name), message="更新成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.delete("/apps/{app_id}")
|
|
async def delete_oa_app(
|
|
app_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
oa_crud.delete_app(db, app_id, tenant_no=tenant_no, user_id=user.get("user_id"))
|
|
return success_response(None, message="删除成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.get("/apps/{app_id}/draft")
|
|
async def get_oa_app_draft(
|
|
app_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = oa_crud.get_or_create_draft(
|
|
db, app_id, tenant_no=tenant_no, user_id=user.get("user_id")
|
|
)
|
|
return success_response(data)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.put("/apps/{app_id}/draft")
|
|
async def save_oa_app_draft(
|
|
app_id: str,
|
|
body: OaDraftSaveBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = oa_crud.save_draft(
|
|
db,
|
|
app_id,
|
|
tenant_no=tenant_no,
|
|
basic=body.basic,
|
|
form_schema_json=body.form_schema_json,
|
|
flow_tree_json=body.flow_tree_json,
|
|
advanced_settings_json=body.advanced_settings_json,
|
|
user_id=user.get("user_id"),
|
|
)
|
|
return success_response(data, message="草稿已保存")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/apps/{app_id}/publish")
|
|
async def publish_oa_app(
|
|
app_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_publish import publish_app
|
|
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data, errors = publish_app(
|
|
db, app_id, tenant_no=tenant_no, user_id=user.get("user_id")
|
|
)
|
|
if errors:
|
|
return error_response(400, "发布校验未通过", data={"errors": errors})
|
|
return success_response(data, message="发布成功")
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 运行时:模板 / 实例 / 任务
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class OaStartInstanceBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
app_id: str = Field(..., alias="appId")
|
|
form_data: Optional[Dict[str, Any]] = Field(None, alias="formData")
|
|
title: Optional[str] = None
|
|
initiator_dept_id: Optional[str] = Field(None, alias="initiatorDeptId")
|
|
initiator_select_user_ids: Optional[List[str]] = Field(None, alias="initiatorSelectUserIds")
|
|
related_instance_ids: Optional[List[str]] = Field(None, alias="relatedInstanceIds")
|
|
source_instance_id: Optional[str] = Field(None, alias="sourceInstanceId")
|
|
|
|
|
|
class OaTaskActionBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
comment: Optional[str] = None
|
|
|
|
|
|
class OaAddSignBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
user_ids: List[str] = Field(default_factory=list, alias="userIds")
|
|
comment: Optional[str] = None
|
|
|
|
|
|
class OaResubmitBody(BaseModel):
|
|
model_config = ConfigDict(populate_by_name=True)
|
|
form_data: Optional[Dict[str, Any]] = Field(None, alias="formData")
|
|
initiator_select_user_ids: Optional[List[str]] = Field(None, alias="initiatorSelectUserIds")
|
|
|
|
|
|
@router.get("/templates")
|
|
async def list_oa_templates(
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services import oa_engine
|
|
|
|
tenant_no = _get_tenant_no(db, user)
|
|
items = oa_engine.list_templates(db, tenant_no=tenant_no, user_id=user.get("user_id") or "")
|
|
return success_response({"list": items})
|
|
|
|
|
|
@router.get("/templates/{app_id}")
|
|
async def get_oa_template(
|
|
app_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, get_template_detail
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = get_template_detail(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
app_id=app_id,
|
|
user_id=user.get("user_id") or "",
|
|
)
|
|
return success_response(data)
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.get("/templates/{app_id}/flow-preview")
|
|
async def preview_oa_template_flow(
|
|
app_id: str,
|
|
initiator_select_user_ids: Optional[str] = Query(None, alias="initiatorSelectUserIds"),
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""发起前预览审批链(解析具体审批人)。"""
|
|
from app.services.oa_engine import OaEngineError, preview_start_flow
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
uid = user.get("user_id") or ""
|
|
dept_id = None
|
|
if uid:
|
|
row = db.query(SysUser).filter(SysUser.id == uid, SysUser.del_flag == 0).first()
|
|
if row:
|
|
dept_id = row.dept_id
|
|
select_ids = None
|
|
if initiator_select_user_ids:
|
|
select_ids = [x.strip() for x in initiator_select_user_ids.split(",") if x.strip()]
|
|
data = preview_start_flow(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
app_id=app_id,
|
|
initiator_user_id=uid,
|
|
initiator_dept_id=dept_id,
|
|
initiator_select_user_ids=select_ids,
|
|
)
|
|
return success_response(data)
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/instances")
|
|
async def start_oa_instance(
|
|
body: OaStartInstanceBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, start_instance
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = start_instance(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
app_id=body.app_id,
|
|
initiator_user_id=user.get("user_id") or "",
|
|
initiator_dept_id=body.initiator_dept_id,
|
|
form_data=body.form_data,
|
|
title=body.title,
|
|
initiator_select_user_ids=body.initiator_select_user_ids,
|
|
related_instance_ids=body.related_instance_ids,
|
|
source_instance_id=body.source_instance_id,
|
|
)
|
|
return success_response(data, message="发起成功")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.get("/instances/{instance_id}")
|
|
async def get_oa_instance(
|
|
instance_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, get_instance_detail
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
return success_response(get_instance_detail(db, instance_id, tenant_no=tenant_no))
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.get("/tasks/{kind}")
|
|
async def list_oa_tasks(
|
|
kind: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, list_tasks
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
items = list_tasks(
|
|
db, tenant_no=tenant_no, user_id=user.get("user_id") or "", kind=kind
|
|
)
|
|
return success_response({"list": items})
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/tasks/{task_id}/approve")
|
|
async def approve_oa_task(
|
|
task_id: str,
|
|
body: Optional[OaTaskActionBody] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, complete_task
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = complete_task(
|
|
db,
|
|
task_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user.get("user_id") or "",
|
|
action="approve",
|
|
comment=(body.comment if body else None),
|
|
)
|
|
return success_response(data, message="已同意")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/tasks/{task_id}/reject")
|
|
async def reject_oa_task(
|
|
task_id: str,
|
|
body: Optional[OaTaskActionBody] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, complete_task
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = complete_task(
|
|
db,
|
|
task_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user.get("user_id") or "",
|
|
action="reject",
|
|
comment=(body.comment if body else None),
|
|
)
|
|
return success_response(data, message="已拒绝")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/tasks/{task_id}/return")
|
|
async def return_oa_task(
|
|
task_id: str,
|
|
body: Optional[OaTaskActionBody] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, return_task
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = return_task(
|
|
db,
|
|
task_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user.get("user_id") or "",
|
|
comment=(body.comment if body else None),
|
|
)
|
|
return success_response(data, message="已打回")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/instances/{instance_id}/resubmit")
|
|
async def resubmit_oa_instance(
|
|
instance_id: str,
|
|
body: Optional[OaResubmitBody] = None,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, resubmit_instance
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = resubmit_instance(
|
|
db,
|
|
instance_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user.get("user_id") or "",
|
|
form_data=(body.form_data if body else None),
|
|
initiator_select_user_ids=(body.initiator_select_user_ids if body else None),
|
|
)
|
|
return success_response(data, message="已再次提交")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/tasks/{task_id}/add-sign")
|
|
async def add_sign_oa_task(
|
|
task_id: str,
|
|
body: OaAddSignBody,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, add_sign
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = add_sign(
|
|
db,
|
|
task_id,
|
|
tenant_no=tenant_no,
|
|
user_id=user.get("user_id") or "",
|
|
user_ids=body.user_ids,
|
|
comment=body.comment,
|
|
)
|
|
return success_response(data, message="加签成功")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|
|
|
|
|
|
@router.post("/instances/{instance_id}/withdraw")
|
|
async def withdraw_oa_instance(
|
|
instance_id: str,
|
|
user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.services.oa_engine import OaEngineError, withdraw_instance
|
|
|
|
try:
|
|
tenant_no = _get_tenant_no(db, user)
|
|
data = withdraw_instance(
|
|
db, instance_id, tenant_no=tenant_no, user_id=user.get("user_id") or ""
|
|
)
|
|
return success_response(data, message="已撤销")
|
|
except OaEngineError as e:
|
|
return error_response(400, str(e))
|