投标待办加入提交人
This commit is contained in:
109
User/utils.py
109
User/utils.py
@@ -594,9 +594,11 @@ def get_approvers_from_record(business_record, approval=None):
|
||||
flow_part = flow_part.split("(按顺序审批)")[0]
|
||||
# 分割审核人(使用 → 分隔)
|
||||
approvers_list = [a.strip() for a in flow_part.split("→") if a.strip()]
|
||||
# 移除最后的"财务"或"财务部"(兼容两种格式)
|
||||
if approvers_list and approvers_list[-1].strip() in ("财务", "财务部"):
|
||||
approvers_list = approvers_list[:-1]
|
||||
# 移除最后的"财务"或"财务部"(兼容两种格式),以及"申请人(待查看)"(投标/立项最后一步)
|
||||
if approvers_list:
|
||||
last = approvers_list[-1].strip()
|
||||
if last in ("财务", "财务部") or last == "申请人(待查看)":
|
||||
approvers_list = approvers_list[:-1]
|
||||
if approvers_list:
|
||||
logger.info(f"get_approvers_from_record: 从 Approval.content 解析审核人列表: {approvers_list}")
|
||||
return approvers_list
|
||||
@@ -651,6 +653,29 @@ def process_approval_flow(approval, business_record, current_approver, state,
|
||||
|
||||
return True, None
|
||||
|
||||
# 申请人待查看阶段:当前步骤是申请人待查看,申请人查看后完成(投标/立项不再给财务部)
|
||||
applicant = getattr(approval, 'applicant', None)
|
||||
if approval.state == "待查看" and applicant and approval.personincharge == applicant:
|
||||
if state == "已通过" or not state:
|
||||
approval.state = "已通过"
|
||||
if "已通过" not in approval.content:
|
||||
approval.content = (approval.content or "") + ",申请人已查看"
|
||||
approval.save(update_fields=['state', 'content'])
|
||||
if business_record and hasattr(business_record, 'state'):
|
||||
business_record.state = final_state_map.get("已通过", "已通过")
|
||||
business_record.save(update_fields=['state'])
|
||||
return True, None
|
||||
if state == "未通过":
|
||||
approval.state = "未通过"
|
||||
if rejection_reason:
|
||||
approval.rejection_reason = rejection_reason
|
||||
approval.save(update_fields=['state', 'rejection_reason'])
|
||||
if business_record and hasattr(business_record, 'state'):
|
||||
business_record.state = final_state_map.get("未通过", "未通过")
|
||||
business_record.save(update_fields=['state'])
|
||||
return True, None
|
||||
return False, None
|
||||
|
||||
# 检查当前是否已经是财务审核(部门ID或“财务”字符串均视为财务阶段)
|
||||
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
|
||||
# 财务部只需要查看,不需要审批,查看后直接完成
|
||||
@@ -729,18 +754,27 @@ def process_approval_flow(approval, business_record, current_approver, state,
|
||||
logger.info(f"process_approval_flow: 已更新审批记录,personincharge={next_approver}, state=审核中")
|
||||
return False, None
|
||||
else:
|
||||
# 最后一个审核人,抄送财务
|
||||
# 最后一个审核人已通过:投标/立项转申请人待查看,其他类型抄送财务
|
||||
applicant = getattr(approval, 'applicant', None)
|
||||
if approval_type in ("投标登记", "立项登记") and applicant:
|
||||
logger.info(f"process_approval_flow: 最后一个审核人已审核,流转到申请人待查看: {applicant}")
|
||||
approval.personincharge = applicant
|
||||
approval.state = "待查看"
|
||||
if "待申请人查看" not in (approval.content or ""):
|
||||
approval.content = (approval.content or "") + ",待申请人查看"
|
||||
approval.save(update_fields=['state', 'personincharge', 'content'])
|
||||
# 不更新业务记录状态,等申请人查看后再设为已通过
|
||||
return False, None
|
||||
# 其他类型:抄送财务
|
||||
logger.info(f"process_approval_flow: 最后一个审核人已审核,流转到财务部")
|
||||
finance_personincharge = get_finance_personincharge_value()
|
||||
approval.personincharge = finance_personincharge
|
||||
approval.state = "已抄送财务"
|
||||
if "已抄送财务" not in approval.content and "已抄送财务部" not in approval.content:
|
||||
approval.content = approval.content + ",已抄送财务部"
|
||||
if "已抄送财务" not in (approval.content or "") and "已抄送财务部" not in (approval.content or ""):
|
||||
approval.content = (approval.content or "") + ",已抄送财务部"
|
||||
approval.save(update_fields=['state', 'personincharge', 'content'])
|
||||
|
||||
if business_record and hasattr(business_record, 'state'):
|
||||
# 抄送财务时就已经审核通过,财务只是查看
|
||||
# 使用 final_state_map 确保状态映射正确(如待办类型:已通过 -> 已完成)
|
||||
final_state = final_state_map.get("已通过", "已通过")
|
||||
business_record.state = final_state
|
||||
business_record.save(update_fields=['state'])
|
||||
@@ -750,13 +784,14 @@ def process_approval_flow(approval, business_record, current_approver, state,
|
||||
|
||||
|
||||
def create_approval_with_team_logic(team_name, approvers, title, content, approval_type, user_id,
|
||||
business_record=None, today=None):
|
||||
business_record=None, today=None, applicant=None):
|
||||
"""
|
||||
根据团队类型创建审批记录(统一逻辑)
|
||||
|
||||
规则:
|
||||
- 个人团队(personal):直接抄送财务(personincharge=财务部ID,state="已抄送财务")
|
||||
- 团队(team):需要审核人,按顺序审核,最后抄送财务
|
||||
- 投标登记/立项登记:最后一步给申请人,生成「待查看」待办,申请人查看后完成(不再给财务部)
|
||||
- 其他类型:团队(team)需要审核人,按顺序审核,最后抄送财务
|
||||
- 无团队:直接抄送财务
|
||||
|
||||
注意:personincharge字段统一使用财务部ID(优先)或回退到"财务"字符串
|
||||
@@ -764,15 +799,13 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
Args:
|
||||
team_name: 团队名称
|
||||
approvers: 审核人列表(可以是数组或字符串,多人团队时需要)
|
||||
- 推荐格式:用户ID列表,如 [1, 2, 3] 或 ["1", "2", "3"]
|
||||
- 兼容格式:用户名列表,如 ["张三", "李四", "王五"]
|
||||
- 字符串格式:逗号分隔的ID或用户名,如 "1,2,3" 或 "张三,李四,王五"
|
||||
title: 审批标题
|
||||
content: 审批内容
|
||||
approval_type: 审批类型(如"立项登记"、"付款申请"等)
|
||||
approval_type: 审批类型(如"立项登记"、"投标登记"、"付款申请"等)
|
||||
user_id: 关联的业务ID(字符串)
|
||||
business_record: 业务记录对象(可选,用于更新状态和存储approvers_order)
|
||||
business_record: 业务记录对象(可选)
|
||||
today: 日期字符串(可选,格式:YYYY-MM-DD)
|
||||
applicant: 申请人用户名(可选,投标/立项时填,最后一步生成待查看待办给申请人)
|
||||
|
||||
Returns:
|
||||
tuple: (approval对象, approvers_order_json, 是否需要审核)
|
||||
@@ -825,7 +858,12 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
# 创建审批记录,第一个审核人
|
||||
first_approver = approvers_list[0]
|
||||
approvers_str = ' → '.join(approvers_list) # 使用箭头表示顺序
|
||||
content_with_flow = f"{content},审批流程:{approvers_str} → 财务部(按顺序审批),当前审批人:{first_approver}"
|
||||
# 投标登记/立项登记:最后一步给申请人(待查看),不再给财务部
|
||||
if approval_type in ("投标登记", "立项登记") and applicant:
|
||||
flow_suffix = " → 申请人(待查看)"
|
||||
else:
|
||||
flow_suffix = " → 财务部(按顺序审批)"
|
||||
content_with_flow = f"{content},审批流程:{approvers_str}{flow_suffix},当前审批人:{first_approver}"
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -838,7 +876,8 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
personincharge=first_approver,
|
||||
state="审核中",
|
||||
type=approval_type,
|
||||
user_id=str(user_id)
|
||||
user_id=str(user_id),
|
||||
applicant=applicant
|
||||
)
|
||||
|
||||
logger.info(f"create_approval_with_team_logic: 审批记录已创建 - ID={approval.id}, personincharge={approval.personincharge}, state={approval.state}")
|
||||
@@ -848,7 +887,22 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
# 如果没有传入审核人,则根据团队类型判断
|
||||
# 判断团队类型
|
||||
if not team_name or not team or (team and team.team_type == 'personal'):
|
||||
# 个人团队或无团队:直接到财务团队审核
|
||||
# 投标登记/立项登记且传入了申请人:最后一步给申请人,生成待查看待办(不再给财务部)
|
||||
if approval_type in ("投标登记", "立项登记") and applicant:
|
||||
content_to_save = content + ",待申请人查看"
|
||||
approval = Approval.objects.create(
|
||||
title=title,
|
||||
content=content_to_save,
|
||||
times=today,
|
||||
personincharge=applicant,
|
||||
state="待查看",
|
||||
type=approval_type,
|
||||
user_id=str(user_id),
|
||||
applicant=applicant
|
||||
)
|
||||
# 不更新业务记录状态,等申请人查看后再设为已通过
|
||||
return approval, None, False
|
||||
# 其他类型:个人团队或无团队,直接到财务团队审核
|
||||
finance_personincharge = get_finance_personincharge_value()
|
||||
content_to_save = content
|
||||
if "已抄送财务" not in content and "已抄送财务部" not in content:
|
||||
@@ -861,11 +915,11 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
personincharge=finance_personincharge,
|
||||
state="已抄送财务",
|
||||
type=approval_type,
|
||||
user_id=str(user_id)
|
||||
user_id=str(user_id),
|
||||
applicant=applicant
|
||||
)
|
||||
|
||||
# 更新业务记录状态:抄送财务时就已经审核通过,财务只是查看
|
||||
# 对于待办和结案申请类型,状态应该是"已完成",其他类型是"已通过"
|
||||
if business_record:
|
||||
if approval_type in ["待办", "结案申请"]:
|
||||
business_record.state = "已完成"
|
||||
@@ -911,8 +965,12 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
|
||||
# 创建审批记录,第一个审核人
|
||||
first_approver = approvers_list[0]
|
||||
approvers_str = ' → '.join(approvers_list) # 使用箭头表示顺序
|
||||
content_with_flow = f"{content},审批流程:{approvers_str} → 财务部(按顺序审批),当前审批人:{first_approver}"
|
||||
approvers_str = ' → '.join(approvers_list)
|
||||
if approval_type in ("投标登记", "立项登记") and applicant:
|
||||
flow_suffix = " → 申请人(待查看)"
|
||||
else:
|
||||
flow_suffix = " → 财务部(按顺序审批)"
|
||||
content_with_flow = f"{content},审批流程:{approvers_str}{flow_suffix},当前审批人:{first_approver}"
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -925,7 +983,8 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
personincharge=first_approver,
|
||||
state="审核中",
|
||||
type=approval_type,
|
||||
user_id=str(user_id)
|
||||
user_id=str(user_id),
|
||||
applicant=applicant
|
||||
)
|
||||
|
||||
logger.info(f"create_approval_with_team_logic: 审批记录已创建 - ID={approval.id}, personincharge={approval.personincharge}, state={approval.state}")
|
||||
@@ -946,11 +1005,11 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
|
||||
personincharge=finance_personincharge,
|
||||
state="已抄送财务",
|
||||
type=approval_type,
|
||||
user_id=str(user_id)
|
||||
user_id=str(user_id),
|
||||
applicant=applicant
|
||||
)
|
||||
|
||||
# 更新业务记录状态:抄送财务时就已经审核通过,财务只是查看
|
||||
# 对于待办和结案申请类型,状态应该是"已完成",其他类型是"已通过"
|
||||
if business_record:
|
||||
if approval_type in ["待办", "结案申请"]:
|
||||
business_record.state = "已完成"
|
||||
|
||||
@@ -802,8 +802,8 @@ class roxyExhibition(APIView):
|
||||
# 单个值
|
||||
query = Q(state=filter_state)
|
||||
else:
|
||||
# 默认状态筛选:审核中、已抄送财务;非财务也包含"已通过"以便按申请人/审批人过滤后展示(待办、投标登记等)
|
||||
query = Q(state__in=["审核中", "已抄送财务", "已通过"])
|
||||
# 默认状态筛选:审核中、已抄送财务、待查看(投标/立项最后一步给申请人)、已通过
|
||||
query = Q(state__in=["审核中", "已抄送财务", "待查看", "已通过"])
|
||||
|
||||
# 添加筛选条件
|
||||
if filter_type:
|
||||
@@ -1082,23 +1082,21 @@ class roxyExhibition(APIView):
|
||||
# 计算 approval_status(与返回数据时的逻辑保持一致)
|
||||
approval_status = "审批中" # 默认状态
|
||||
|
||||
# 待办类型的状态显示逻辑:审核中->审核中,已抄送财务->待查看,已通过->已完成
|
||||
# 待办类型的状态显示逻辑:审核中->审核中,已抄送财务/待查看->待查看,已通过->已完成
|
||||
if info.type == "待办":
|
||||
if info.state == "审核中":
|
||||
approval_status = "审核中"
|
||||
elif info.state == "已抄送财务":
|
||||
elif info.state in ("已抄送财务", "待查看"):
|
||||
approval_status = "待查看"
|
||||
elif info.state == "已通过":
|
||||
approval_status = "已完成"
|
||||
elif info.state == "未通过":
|
||||
approval_status = "审核中" # 未通过也可以继续审批流程
|
||||
else:
|
||||
# 其他类型的状态显示逻辑:审核中->审批中,已抄送财务->待查看,已通过->已完成
|
||||
if info.state == "已抄送财务":
|
||||
# 已抄送财务时,显示"待查看"(财务部需要查看)
|
||||
# 其他类型:审核中->审批中,已抄送财务/待查看->待查看,已通过->已完成
|
||||
if info.state in ("已抄送财务", "待查看"):
|
||||
approval_status = "待查看"
|
||||
elif info.state == "已通过":
|
||||
# 审批记录状态为"已通过"(通常是财务查看后),显示"已完成"
|
||||
approval_status = "已完成"
|
||||
elif info.state == "审核中":
|
||||
approval_status = "审批中"
|
||||
@@ -1326,23 +1324,21 @@ class roxyExhibition(APIView):
|
||||
# - "已通过" -> "已完成"(财务查看了之后)
|
||||
approval_status = "审批中" # 默认状态
|
||||
|
||||
# 待办类型的状态显示逻辑:审核中->审核中,已抄送财务->待查看,已通过->已完成
|
||||
# 待办类型的状态显示逻辑:审核中->审核中,已抄送财务/待查看->待查看,已通过->已完成
|
||||
if info.type == "待办":
|
||||
if info.state == "审核中":
|
||||
approval_status = "审核中"
|
||||
elif info.state == "已抄送财务":
|
||||
elif info.state in ("已抄送财务", "待查看"):
|
||||
approval_status = "待查看"
|
||||
elif info.state == "已通过":
|
||||
approval_status = "已完成"
|
||||
elif info.state == "未通过":
|
||||
approval_status = "审核中" # 未通过也可以继续审批流程
|
||||
else:
|
||||
# 其他类型的状态显示逻辑:审核中->审批中,已抄送财务->待查看,已通过->已完成
|
||||
if info.state == "已抄送财务":
|
||||
# 已抄送财务时,显示"待查看"(财务部需要查看)
|
||||
# 其他类型:审核中->审批中,已抄送财务/待查看->待查看(投标/立项最后一步给申请人),已通过->已完成
|
||||
if info.state in ("已抄送财务", "待查看"):
|
||||
approval_status = "待查看"
|
||||
elif info.state == "已通过":
|
||||
# 审批记录状态为"已通过"(通常是财务查看后),显示"已完成"
|
||||
approval_status = "已完成"
|
||||
elif info.state == "审核中":
|
||||
approval_status = "审批中"
|
||||
@@ -1989,6 +1985,10 @@ class approvalProcessing(APIView):
|
||||
except ProjectRegistration.DoesNotExist:
|
||||
return Response({'status': 'error', 'message': '立项登记记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
# 申请人待查看阶段:只传 type 和 id 不传 state 时,视为申请人查看完成(默认已通过)
|
||||
if approval.state == "待查看" and getattr(approval, 'applicant', None) and approval.personincharge == approval.applicant and not state:
|
||||
state = "已通过"
|
||||
|
||||
# 使用统一的审核流程处理函数
|
||||
from User.utils import process_approval_flow
|
||||
current_approver = approval.personincharge
|
||||
@@ -2013,6 +2013,10 @@ class approvalProcessing(APIView):
|
||||
except Bid.DoesNotExist:
|
||||
return Response({'status': 'error', 'message': '投标登记记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
# 申请人待查看阶段:只传 type 和 id 不传 state 时,视为申请人查看完成(默认已通过)
|
||||
if approval.state == "待查看" and getattr(approval, 'applicant', None) and approval.personincharge == approval.applicant and not state:
|
||||
state = "已通过"
|
||||
|
||||
# 使用统一的审核流程处理函数
|
||||
from User.utils import process_approval_flow
|
||||
current_approver = approval.personincharge
|
||||
|
||||
@@ -698,14 +698,10 @@ class Project(APIView):
|
||||
approval_type="立项登记",
|
||||
user_id=pro.id,
|
||||
business_record=pro,
|
||||
today=formatted_date
|
||||
today=formatted_date,
|
||||
applicant=applicant_name
|
||||
)
|
||||
|
||||
# 写入申请人,便于待办列表展示及“审批完成后申请人可见”
|
||||
if approval and applicant_name:
|
||||
approval.applicant = applicant_name
|
||||
approval.save(update_fields=['applicant'])
|
||||
|
||||
# 如果返回None且需要审核,说明缺少审核人
|
||||
if approval is None and needs_approval:
|
||||
return Response({
|
||||
@@ -1009,11 +1005,9 @@ class EditProject(APIView):
|
||||
approval_type="立项登记",
|
||||
user_id=pro.id,
|
||||
business_record=pro,
|
||||
today=formatted_date
|
||||
today=formatted_date,
|
||||
applicant=applicant_name
|
||||
)
|
||||
if approval and applicant_name:
|
||||
approval.applicant = applicant_name
|
||||
approval.save(update_fields=['applicant'])
|
||||
if approval is None and needs_approval:
|
||||
return Response({
|
||||
'status': 'error',
|
||||
@@ -1116,9 +1110,10 @@ class BidRegistration(APIView):
|
||||
|
||||
import datetime
|
||||
|
||||
# 获取当前用户信息(用于团队信息)
|
||||
# 获取当前用户信息(用于团队信息及申请人)
|
||||
token = request.META.get('token')
|
||||
team_name = None
|
||||
user = None
|
||||
try:
|
||||
user = User.objects.get(token=token, is_deleted=False)
|
||||
team_name = user.team
|
||||
@@ -1161,14 +1156,10 @@ class BidRegistration(APIView):
|
||||
approval_type="投标登记",
|
||||
user_id=bib.id,
|
||||
business_record=bib,
|
||||
today=formatted_date
|
||||
today=formatted_date,
|
||||
applicant=applicant_name
|
||||
)
|
||||
|
||||
# 写入申请人,便于待办列表展示及“审批完成后申请人可见”
|
||||
if approval and applicant_name:
|
||||
approval.applicant = applicant_name
|
||||
approval.save(update_fields=['applicant'])
|
||||
|
||||
# 如果返回None且需要审核,说明缺少审核人
|
||||
if approval is None and needs_approval:
|
||||
return Response({
|
||||
@@ -1291,11 +1282,9 @@ class EditBid(APIView):
|
||||
approval_type="投标登记",
|
||||
user_id=bid.id,
|
||||
business_record=bid,
|
||||
today=formatted_date
|
||||
today=formatted_date,
|
||||
applicant=applicant_name
|
||||
)
|
||||
if approval and applicant_name:
|
||||
approval.applicant = applicant_name
|
||||
approval.save(update_fields=['applicant'])
|
||||
if approval is None and needs_approval:
|
||||
return Response({
|
||||
'status': 'error',
|
||||
|
||||
Reference in New Issue
Block a user