752 lines
28 KiB
Python
752 lines
28 KiB
Python
"""CRM 合同子模块路由 — 变更/模板/审批独立页"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from fastapi import Depends, Query, Request
|
|
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.core.tenant_context import get_tenant_no
|
|
from app.crud.crm.data_scope_helpers import crm_user_info
|
|
from app.crud.crm.contract import (
|
|
create_contract_change,
|
|
create_contract_template,
|
|
export_contract_changes,
|
|
export_contract_templates,
|
|
execute_change,
|
|
get_contract_change_detail,
|
|
get_contract_template_detail,
|
|
list_contract_changes,
|
|
list_contract_templates,
|
|
soft_delete_contract_changes,
|
|
soft_delete_contract_templates,
|
|
submit_change_approval,
|
|
toggle_contract_template_active,
|
|
total_pages,
|
|
update_contract_change,
|
|
update_contract_template,
|
|
withdraw_change,
|
|
)
|
|
from app.crud.crm.contract_approval import (
|
|
approve_pass,
|
|
approve_reject,
|
|
approve_transfer,
|
|
export_contract_approvals,
|
|
get_contract_approval_detail,
|
|
list_contract_approvals_page,
|
|
refresh_approver_names,
|
|
)
|
|
from app.schemas.crm.contract import (
|
|
ContractApprovalExportBody,
|
|
ContractApprovalListQuery,
|
|
ContractApprovalPassBody,
|
|
ContractApprovalRefreshNamesBody,
|
|
ContractApprovalRejectBody,
|
|
ContractApprovalTransferBody,
|
|
ContractChangeCreateBody,
|
|
ContractChangeExportBody,
|
|
ContractChangeListQuery,
|
|
ContractChangeSubmitBody,
|
|
ContractChangeUpdateBody,
|
|
ContractTemplateCreateBody,
|
|
ContractTemplateExportBody,
|
|
ContractTemplateListQuery,
|
|
ContractTemplateUpdateBody,
|
|
)
|
|
from app.utils.crm_export_columns import (
|
|
CONTRACT_APPROVAL_EXPORT_COLUMNS,
|
|
CONTRACT_CHANGE_EXPORT_COLUMNS,
|
|
CONTRACT_TEMPLATE_EXPORT_COLUMNS,
|
|
)
|
|
from app.utils.excel_export import (
|
|
ExportValidationError,
|
|
export_rows_to_xlsx_response,
|
|
filter_export_columns,
|
|
)
|
|
from app.api.crm import _filter_export_rows_by_ids
|
|
|
|
|
|
def register_contract_sub_routes(router):
|
|
# --- 合同变更 ---
|
|
@router.get("/contract/change/list")
|
|
async def contract_change_list(
|
|
request: Request,
|
|
pageNum: int = Query(1, ge=1),
|
|
pageSize: int = Query(10, ge=1, le=500),
|
|
contractId: Optional[str] = None,
|
|
contractNo: Optional[str] = None,
|
|
contractName: Optional[str] = None,
|
|
changeType: Optional[str] = None,
|
|
approvalStatus: Optional[str] = None,
|
|
beginTime: Optional[str] = None,
|
|
endTime: Optional[str] = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
query = ContractChangeListQuery(
|
|
pageNum=pageNum,
|
|
pageSize=pageSize,
|
|
contractId=contractId,
|
|
contractNo=contractNo,
|
|
contractName=contractName,
|
|
changeType=changeType,
|
|
approvalStatus=approvalStatus,
|
|
beginTime=beginTime,
|
|
endTime=endTime,
|
|
)
|
|
filters = query.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if query.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in query.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
# 列头漏斗等未在签名中声明的 query 参数一并透传
|
|
skip_keys = {"pageNum", "pageSize", *filters.keys()}
|
|
for key, val in request.query_params.multi_items():
|
|
if key in skip_keys or val is None or str(val).strip() == "":
|
|
continue
|
|
filters[key] = val
|
|
rows, total = list_contract_changes(
|
|
db,
|
|
tenant_no,
|
|
user_info=user_info,
|
|
page=query.pageNum,
|
|
page_size=query.pageSize,
|
|
filters=filters,
|
|
)
|
|
return success_response(
|
|
{
|
|
"list": rows,
|
|
"rows": rows,
|
|
"total": total,
|
|
"pageNum": query.pageNum,
|
|
"pageSize": query.pageSize,
|
|
"totalPages": total_pages(total, query.pageSize),
|
|
}
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.get("/contract/change/{change_id}")
|
|
async def contract_change_detail(
|
|
change_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
detail = get_contract_change_detail(db, change_id, tenant_no=tenant_no, user_info=user_info)
|
|
return success_response(detail)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/change")
|
|
async def contract_change_add(
|
|
body: ContractChangeCreateBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
dept_id = _user.get("dept_id", "") or _user.get("create_dept_id", "") or ""
|
|
detail = create_contract_change(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
data=body.model_dump(by_alias=True),
|
|
user_id=user_id,
|
|
dept_id=dept_id,
|
|
)
|
|
return success_response(detail["id"], message="新增成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/change")
|
|
async def contract_change_edit(
|
|
body: ContractChangeUpdateBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
data = body.model_dump(by_alias=True)
|
|
change_id = data.pop("id")
|
|
detail = update_contract_change(
|
|
db,
|
|
change_id,
|
|
tenant_no=tenant_no,
|
|
data=data,
|
|
user_id=user_id,
|
|
user_info=user_info,
|
|
)
|
|
return success_response(detail, message="修改成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.delete("/contract/change/{ids}")
|
|
async def contract_change_remove(
|
|
ids: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
id_list = [x.strip() for x in ids.split(",") if x.strip()]
|
|
soft_delete_contract_changes(db, id_list, tenant_no=tenant_no, user_info=user_info)
|
|
return success_response(None, message="删除成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/change/submitApproval")
|
|
async def contract_change_submit_approval(
|
|
body: ContractChangeSubmitBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
submit_change_approval(
|
|
db,
|
|
body.id,
|
|
tenant_no=tenant_no,
|
|
approver_ids=body.approverIds,
|
|
remark=body.remark or "",
|
|
user_id=user_id,
|
|
)
|
|
return success_response(None, message="提交成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/change/withdraw/{change_id}")
|
|
async def contract_change_withdraw(
|
|
change_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
withdraw_change(db, change_id, tenant_no=tenant_no, user_id=user_id)
|
|
return success_response(None, message="撤回成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/change/execute/{change_id}")
|
|
async def contract_change_execute(
|
|
change_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
execute_change(db, change_id, tenant_no=tenant_no, user_id=user_id)
|
|
return success_response(None, message="执行成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/change/export")
|
|
async def contract_change_export(
|
|
body: ContractChangeExportBody = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
list_body = body or ContractChangeExportBody()
|
|
filters = list_body.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if list_body.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in list_body.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
rows = export_contract_changes(db, tenant_no, filters=filters)
|
|
rows = _filter_export_rows_by_ids(rows, getattr(list_body, "ids", None) or getattr(body, "ids", None))
|
|
export_cols = filter_export_columns(CONTRACT_CHANGE_EXPORT_COLUMNS, getattr(list_body, "columns", None) or getattr(body, "columns", None))
|
|
return export_rows_to_xlsx_response(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
sheet_title="合同变更记录",
|
|
columns=export_cols,
|
|
rows=rows,
|
|
filename_stem=f"合同变更_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
include_legacy_filename=False,
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
# --- 合同模板库 ---
|
|
@router.get("/contract/template/list")
|
|
async def contract_template_list(
|
|
request: Request,
|
|
pageNum: int = Query(1, ge=1),
|
|
pageSize: int = Query(10, ge=1, le=500),
|
|
templateNo: Optional[str] = None,
|
|
templateName: Optional[str] = None,
|
|
templateType: Optional[str] = None,
|
|
isActive: Optional[int] = None,
|
|
beginTime: Optional[str] = None,
|
|
endTime: Optional[str] = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
query = ContractTemplateListQuery(
|
|
pageNum=pageNum,
|
|
pageSize=pageSize,
|
|
templateNo=templateNo,
|
|
templateName=templateName,
|
|
templateType=templateType,
|
|
isActive=isActive,
|
|
beginTime=beginTime,
|
|
endTime=endTime,
|
|
)
|
|
filters = query.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if query.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in query.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
skip_keys = {"pageNum", "pageSize", *filters.keys()}
|
|
for key, val in request.query_params.multi_items():
|
|
if key in skip_keys or val is None or str(val).strip() == "":
|
|
continue
|
|
filters[key] = val
|
|
rows, total = list_contract_templates(
|
|
db,
|
|
tenant_no,
|
|
user_info=user_info,
|
|
page=query.pageNum,
|
|
page_size=query.pageSize,
|
|
filters=filters,
|
|
)
|
|
return success_response(
|
|
{
|
|
"list": rows,
|
|
"rows": rows,
|
|
"total": total,
|
|
"pageNum": query.pageNum,
|
|
"pageSize": query.pageSize,
|
|
"totalPages": total_pages(total, query.pageSize),
|
|
}
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.get("/contract/template/{template_id}")
|
|
async def contract_template_detail(
|
|
template_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
detail = get_contract_template_detail(db, template_id, tenant_no=tenant_no)
|
|
return success_response(detail)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/template")
|
|
async def contract_template_add(
|
|
body: ContractTemplateCreateBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
dept_id = _user.get("dept_id", "") or _user.get("create_dept_id", "") or ""
|
|
detail = create_contract_template(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
data=body.model_dump(by_alias=True),
|
|
user_id=user_id,
|
|
dept_id=dept_id,
|
|
)
|
|
return success_response(detail["id"], message="新增成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/template")
|
|
async def contract_template_edit(
|
|
body: ContractTemplateUpdateBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
data = body.model_dump(by_alias=True)
|
|
template_id = data.pop("id")
|
|
detail = update_contract_template(
|
|
db,
|
|
template_id,
|
|
tenant_no=tenant_no,
|
|
data=data,
|
|
user_id=user_id,
|
|
user_info=user_info,
|
|
)
|
|
return success_response(detail, message="修改成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.delete("/contract/template/{ids}")
|
|
async def contract_template_remove(
|
|
ids: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
id_list = [x.strip() for x in ids.split(",") if x.strip()]
|
|
soft_delete_contract_templates(db, id_list, tenant_no=tenant_no, user_info=user_info)
|
|
return success_response(None, message="删除成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/template/enable/{template_id}")
|
|
async def contract_template_enable(
|
|
template_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
toggle_contract_template_active(
|
|
db, template_id, tenant_no=tenant_no, is_active=1, user_id=user_id
|
|
)
|
|
return success_response(None, message="启用成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.put("/contract/template/disable/{template_id}")
|
|
async def contract_template_disable(
|
|
template_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
toggle_contract_template_active(
|
|
db, template_id, tenant_no=tenant_no, is_active=0, user_id=user_id
|
|
)
|
|
return success_response(None, message="停用成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/template/export")
|
|
async def contract_template_export(
|
|
body: ContractTemplateExportBody = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
list_body = body or ContractTemplateExportBody()
|
|
filters = list_body.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if list_body.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in list_body.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
rows = export_contract_templates(db, tenant_no, filters=filters)
|
|
rows = _filter_export_rows_by_ids(rows, getattr(list_body, "ids", None) or getattr(body, "ids", None))
|
|
export_cols = filter_export_columns(CONTRACT_TEMPLATE_EXPORT_COLUMNS, getattr(list_body, "columns", None) or getattr(body, "columns", None))
|
|
return export_rows_to_xlsx_response(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
sheet_title="合同模板",
|
|
columns=export_cols,
|
|
rows=rows,
|
|
filename_stem=f"合同模板_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
include_legacy_filename=False,
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
# --- 审批记录独立页 ---
|
|
@router.get("/contract/approval/list")
|
|
async def contract_approval_list(
|
|
request: Request,
|
|
pageNum: int = Query(1, ge=1),
|
|
pageSize: int = Query(10, ge=1, le=500),
|
|
contractId: Optional[str] = None,
|
|
contractNo: Optional[str] = None,
|
|
contractName: Optional[str] = None,
|
|
approverName: Optional[str] = None,
|
|
approvalResult: Optional[str] = None,
|
|
beginTime: Optional[str] = None,
|
|
endTime: Optional[str] = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
query = ContractApprovalListQuery(
|
|
pageNum=pageNum,
|
|
pageSize=pageSize,
|
|
contractId=contractId,
|
|
contractNo=contractNo,
|
|
contractName=contractName,
|
|
approverName=approverName,
|
|
approvalResult=approvalResult,
|
|
beginTime=beginTime,
|
|
endTime=endTime,
|
|
)
|
|
filters = query.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if query.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in query.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
skip_keys = {"pageNum", "pageSize", *filters.keys()}
|
|
for key, val in request.query_params.multi_items():
|
|
if key in skip_keys or val is None or str(val).strip() == "":
|
|
continue
|
|
filters[key] = val
|
|
rows, total = list_contract_approvals_page(
|
|
db,
|
|
tenant_no,
|
|
page=query.pageNum,
|
|
page_size=query.pageSize,
|
|
filters=filters,
|
|
)
|
|
return success_response(
|
|
{
|
|
"list": rows,
|
|
"rows": rows,
|
|
"total": total,
|
|
"pageNum": query.pageNum,
|
|
"pageSize": query.pageSize,
|
|
"totalPages": total_pages(total, query.pageSize),
|
|
}
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.get("/contract/approval/{approval_id}")
|
|
async def contract_approval_detail(
|
|
approval_id: str,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
detail = get_contract_approval_detail(db, approval_id, tenant_no=tenant_no)
|
|
return success_response(detail)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/approval/pass")
|
|
async def contract_approval_pass(
|
|
body: ContractApprovalPassBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
approve_pass(db, body.id, approval_opinion=body.approvalOpinion or "", user_id=user_id)
|
|
db.commit()
|
|
return success_response(None, message="审批通过")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/approval/reject")
|
|
async def contract_approval_reject(
|
|
body: ContractApprovalRejectBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
approve_reject(db, body.id, approval_opinion=body.approvalOpinion, user_id=user_id)
|
|
db.commit()
|
|
return success_response(None, message="已驳回")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/approval/transfer")
|
|
async def contract_approval_transfer(
|
|
body: ContractApprovalTransferBody,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
user_id = _user.get("user_id", "") or _user.get("id", "")
|
|
approve_transfer(
|
|
db,
|
|
body.id,
|
|
target_approver_id=body.targetApproverId,
|
|
transfer_reason=body.transferReason,
|
|
user_id=user_id,
|
|
)
|
|
db.commit()
|
|
return success_response(None, message="转审成功")
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/approval/export")
|
|
async def contract_approval_export(
|
|
body: ContractApprovalExportBody = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
tenant_no = get_tenant_no(db, _user)
|
|
user_info = crm_user_info(_user)
|
|
list_body = body or ContractApprovalExportBody()
|
|
filters = list_body.model_dump(
|
|
by_alias=True,
|
|
exclude={"pageNum", "pageSize"},
|
|
exclude_none=True,
|
|
)
|
|
if list_body.model_extra:
|
|
filters.update(
|
|
{
|
|
k: v
|
|
for k, v in list_body.model_extra.items()
|
|
if v is not None and str(v).strip() != ""
|
|
}
|
|
)
|
|
rows = export_contract_approvals(db, tenant_no, filters=filters)
|
|
rows = _filter_export_rows_by_ids(rows, getattr(list_body, "ids", None) or getattr(body, "ids", None))
|
|
export_cols = filter_export_columns(CONTRACT_APPROVAL_EXPORT_COLUMNS, getattr(list_body, "columns", None) or getattr(body, "columns", None))
|
|
return export_rows_to_xlsx_response(
|
|
db,
|
|
tenant_no=tenant_no,
|
|
sheet_title="合同审批记录",
|
|
columns=export_cols,
|
|
rows=rows,
|
|
filename_stem=f"合同审批_{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
include_legacy_filename=False,
|
|
)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|
|
|
|
@router.post("/contract/approval/refreshNames")
|
|
async def contract_approval_refresh_names(
|
|
body: ContractApprovalRefreshNamesBody = None,
|
|
_user: dict = Depends(require_admin_or_super_admin),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
try:
|
|
req = body or ContractApprovalRefreshNamesBody()
|
|
count = refresh_approver_names(db, contract_id=req.contractId)
|
|
db.commit()
|
|
return success_response(count)
|
|
except ValueError as e:
|
|
return error_response(400, str(e))
|
|
except Exception as e:
|
|
return error_response(500, str(e))
|