196 lines
6.5 KiB
Python
196 lines
6.5 KiB
Python
"""请假申请 API — 工作流测试"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Optional
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.menu_guard import require_admin_or_super_admin
|
|
from app.core.database import get_db
|
|
from app.core.response import success_response, error_response
|
|
from app.crud import leave as leave_crud
|
|
from app.crud.leave import total_pages
|
|
from app.schemas.leave import LeaveCreate, LeaveUpdate
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(prefix="/web/admin/leave", tags=["请假管理"])
|
|
|
|
_LEAVE_TYPE_MAP = {"personal": "事假", "sick": "病假", "annual": "年假", "other": "其他"}
|
|
|
|
|
|
def _leave_local_callback(db: Session, business_id: str, event: str) -> None:
|
|
if not business_id:
|
|
return
|
|
if event == "completed":
|
|
leave_crud.update_leave_status(db, business_id, "approved")
|
|
elif event == "rejected":
|
|
leave_crud.update_leave_status(db, business_id, "rejected")
|
|
db.commit()
|
|
|
|
|
|
from app.services.workflow_callback import register_local_callback
|
|
register_local_callback("/api/admin/leave/callback", _leave_local_callback)
|
|
|
|
|
|
@router.get("")
|
|
async def list_leaves(
|
|
page: int = Query(1, ge=1),
|
|
pageSize: int = Query(10, ge=1, le=100),
|
|
keyword: Optional[str] = Query(None),
|
|
status: Optional[str] = Query(None),
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _user.get("tenant_no", "")
|
|
user_id = _user.get("user_id") or _user.get("id", "")
|
|
items, total = leave_crud.list_leaves(
|
|
db, page=page, page_size=pageSize, keyword=keyword, status=status,
|
|
tenant_no=tenant_no, create_by=user_id, user_info=_user,
|
|
)
|
|
for item in items:
|
|
item["leaveTypeLabel"] = _LEAVE_TYPE_MAP.get(item.get("leaveType", ""), item.get("leaveType", ""))
|
|
return success_response({
|
|
"list": items, "total": total, "page": page, "pageSize": pageSize,
|
|
"totalPages": total_pages(total, pageSize),
|
|
})
|
|
|
|
|
|
@router.post("")
|
|
async def create_leave(
|
|
body: LeaveCreate,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
tenant_no = _user.get("tenant_no", "")
|
|
user_id = _user.get("user_id") or _user.get("id", "")
|
|
dept_id = _user.get("region_id", "")
|
|
row = leave_crud.create_leave(
|
|
db,
|
|
leave_type=body.leaveType,
|
|
start_date=body.startDate,
|
|
end_date=body.endDate,
|
|
days=body.days,
|
|
reason=body.reason or "",
|
|
tenant_no=tenant_no,
|
|
user_id=user_id,
|
|
dept_id=dept_id,
|
|
remark=body.remark or "",
|
|
)
|
|
db.commit()
|
|
return success_response(leave_crud._row_to_dict(row))
|
|
|
|
|
|
@router.post("/{leave_id}/submit")
|
|
async def submit_leave(
|
|
leave_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
from app.models.models import WfProcessDef
|
|
from app.services.workflow_engine import WorkflowEngine
|
|
|
|
tenant_no = _user.get("tenant_no", "")
|
|
user_id = _user.get("user_id") or _user.get("id", "")
|
|
|
|
leave = leave_crud.get_leave(db, leave_id)
|
|
if not leave:
|
|
return error_response(404, "请假记录不存在")
|
|
|
|
if leave["status"] not in ("draft", "rejected"):
|
|
return error_response(400, "只有草稿或已驳回的请假单可以提交")
|
|
|
|
defn = db.query(WfProcessDef).filter(
|
|
WfProcessDef.process_code == "leave_request",
|
|
WfProcessDef.del_flag == 0,
|
|
WfProcessDef.status == "1",
|
|
).first()
|
|
if not defn:
|
|
return error_response(400, "未找到请假审批流程(leave_request),请先在流程配置中创建并发布")
|
|
|
|
variables = {
|
|
"days": leave["days"],
|
|
"leave_days": leave["days"],
|
|
"leaveType": leave["leaveType"],
|
|
"applicant": user_id,
|
|
}
|
|
|
|
try:
|
|
engine = WorkflowEngine(db)
|
|
instance = engine.start_process(
|
|
process_def_id=defn.id,
|
|
business_type="leave",
|
|
business_id=leave_id,
|
|
starter_user_id=user_id,
|
|
variables=variables,
|
|
callback_url="/api/admin/leave/callback",
|
|
tenant_no=tenant_no,
|
|
user_id=user_id,
|
|
)
|
|
leave_crud.update_leave_status(db, leave_id, "pending", wf_instance_id=instance.id, user_id=user_id)
|
|
db.commit()
|
|
return success_response({"instanceId": instance.id, "status": "pending"})
|
|
except Exception as e:
|
|
db.rollback()
|
|
logger.exception("发起请假审批失败: %s", e)
|
|
return error_response(500, f"发起审批失败: {e}")
|
|
|
|
|
|
@router.post("/callback")
|
|
async def leave_workflow_callback_blocked():
|
|
"""HTTP 回调已禁用:请假审批结果仅允许工作流本地回调(register_local_callback)。"""
|
|
return error_response(
|
|
403,
|
|
"请假审批回调仅支持进程内本地回调,请勿通过 HTTP 调用本接口",
|
|
)
|
|
|
|
|
|
@router.get("/{leave_id}")
|
|
async def get_leave(
|
|
leave_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
item = leave_crud.get_leave(db, leave_id)
|
|
if not item:
|
|
return error_response(404, "请假记录不存在")
|
|
item["leaveTypeLabel"] = _LEAVE_TYPE_MAP.get(item.get("leaveType", ""), item.get("leaveType", ""))
|
|
return success_response(item)
|
|
|
|
|
|
@router.delete("/{leave_id}")
|
|
async def delete_leave(
|
|
leave_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
user_id = _user.get("user_id") or _user.get("id", "")
|
|
leave = leave_crud.get_leave(db, leave_id)
|
|
if not leave:
|
|
return error_response(404, "请假记录不存在")
|
|
if leave["status"] == "pending":
|
|
return error_response(400, "审批中的请假单不能删除")
|
|
leave_crud.soft_delete_leave(db, leave_id, user_id=user_id)
|
|
db.commit()
|
|
return success_response(None)
|
|
|
|
|
|
@router.put("/{leave_id}")
|
|
async def update_leave(
|
|
leave_id: str,
|
|
body: LeaveUpdate,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
user_id = _user.get("user_id") or _user.get("id", "")
|
|
leave = leave_crud.get_leave(db, leave_id)
|
|
if not leave:
|
|
return error_response(404, "请假记录不存在")
|
|
if leave["status"] not in ("draft", "rejected"):
|
|
return error_response(400, "只有草稿或已驳回状态可以编辑")
|
|
leave_crud.update_leave(db, leave_id, user_id=user_id, **body.model_dump(exclude_none=True))
|
|
db.commit()
|
|
return success_response(leave_crud.get_leave(db, leave_id))
|