diff --git a/User/models.py b/User/models.py index 0e3f5a1..b12ac4f 100644 --- a/User/models.py +++ b/User/models.py @@ -59,6 +59,7 @@ class Approval(models.Model): state = models.CharField(max_length=100) # 状态 type = models.CharField(max_length=100) # 类别 user_id = models.CharField(max_length=100) # 事件id + applicant = models.CharField(max_length=100, null=True, blank=True) # 申请人(提交人,用于投标登记、立项等) rejection_reason = models.TextField(null=True, blank=True) # 不通过原因(审核不通过时填写) is_deleted = models.BooleanField(default=False) # 软删除标记 diff --git a/User/views.py b/User/views.py index f2ad044..c5fc067 100644 --- a/User/views.py +++ b/User/views.py @@ -802,12 +802,8 @@ class roxyExhibition(APIView): # 单个值 query = Q(state=filter_state) else: - # 默认状态筛选:审核中 或 已抄送财务 - # 如果是财务部人员,还需要包含"已通过"状态(可以看到已完成的待办) - if is_finance_user: - query = Q(state__in=["审核中", "已抄送财务", "已通过"]) - else: - query = Q(state__in=["审核中", "已抄送财务"]) + # 默认状态筛选:审核中、已抄送财务;非财务也包含"已通过"以便按申请人/审批人过滤后展示(待办、投标登记等) + query = Q(state__in=["审核中", "已抄送财务", "已通过"]) # 添加筛选条件 if filter_type: @@ -867,14 +863,37 @@ class roxyExhibition(APIView): if user_submitted_schedule_ids_str: completed_todo_query = Q(type="待办", state="已通过", user_id__in=user_submitted_schedule_ids_str) - # 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 OR 已通过的待办查询 + # 投标登记审批完成后,申请人与审批人均可见 + completed_bid_query = Q() + completed_bid_applicant = Q(type="投标登记", state="已通过", applicant=user.username) + try: + approved_bid_ids = list(Approval.objects.filter(type="投标登记", state="已通过").values_list('user_id', flat=True)) + bid_ids_where_user_is_approver = [] + if approved_bid_ids: + bid_ids_int = [int(x) for x in approved_bid_ids if str(x).isdigit()] + from business.models import Bid + for bid in Bid.objects.filter(id__in=bid_ids_int, is_deleted=False): + try: + order = json.loads(bid.approvers_order or '[]') + if isinstance(order, list) and user.username in order: + bid_ids_where_user_is_approver.append(bid.id) + except (json.JSONDecodeError, TypeError): + pass + if bid_ids_where_user_is_approver: + completed_bid_query = completed_bid_applicant | Q(type="投标登记", state="已通过", user_id__in=[str(x) for x in bid_ids_where_user_is_approver]) + else: + completed_bid_query = completed_bid_applicant + except Exception: + completed_bid_query = completed_bid_applicant + + # 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 OR 已通过的待办查询 OR 已通过的投标登记(申请人/审批人可见) # 如果用户有部门,使用部门匹配;否则只使用审批员匹配 # 注意:审批员匹配必须精确匹配当前用户名,确保多人团队审核时,只有当前审核人能看到 if user_department_ids_str: - query &= (department_query | person_query | finance_query | completed_todo_query) + query &= (department_query | person_query | finance_query | completed_todo_query | completed_bid_query) else: - # 如果用户没有部门,匹配审批员或财务(仅财务部人员)或已通过的待办 - query &= (person_query | finance_query | completed_todo_query) + # 如果用户没有部门,匹配审批员或财务(仅财务部人员)或已通过的待办或已通过的投标登记 + query &= (person_query | finance_query | completed_todo_query | completed_bid_query) # 添加调试日志 import logging @@ -1409,9 +1428,9 @@ class roxyExhibition(APIView): itme["project_conflicts"] = [] itme["bid_conflicts"] = [] - # 如果是投标登记类型:返回提交人、冲突信息等(与立项相同逻辑) + # 如果是投标登记类型:返回申请人、审批流程、冲突信息等(与立项相同逻辑) if info.type == "投标登记": - # 提交人:优先从 Approval.applicant 取,否则从 content 解析「申请人:xxx」 + # 申请人:优先从 Approval.applicant 取,否则从 content 解析「申请人:xxx」 submitter = getattr(info, 'applicant', None) if not submitter and content and "申请人:" in content: import re @@ -1419,13 +1438,23 @@ class roxyExhibition(APIView): if m: submitter = m.group(1).strip() itme["submitter"] = submitter or "" - # 将提交人拼接到待办展示信息(content)中,便于列表一眼看到 - if submitter and ("提交人:" not in (itme.get("content") or "")): - itme["content"] = (itme.get("content") or "").rstrip() + ",提交人:" + submitter + itme["applicant"] = submitter or "" # 投标待办展示“申请人”字段(审批人--->申请人) try: from business.views import conflict_search bid_id = int(info.user_id) bid = Bid.objects.filter(id=bid_id, is_deleted=False).first() + # 审批流程:从 Bid.approvers_order 解析为名单列表 + approvers_order_list = [] + if bid and getattr(bid, 'approvers_order', None): + try: + order = json.loads(bid.approvers_order or '[]') + approvers_order_list = order if isinstance(order, list) else [] + except (json.JSONDecodeError, TypeError): + pass + itme["approvers_order"] = approvers_order_list # 审批流程(审批人顺序) + # 将申请人拼接到待办展示信息(content)中,便于列表一眼看到 + if submitter and ("申请人:" not in (itme.get("content") or "") and ("提交人:" not in (itme.get("content") or "")): + itme["content"] = (itme.get("content") or "").rstrip() + ",申请人:" + submitter if bid and bid.BiddingUnit: conflict_result = conflict_search(bidding_unit=bid.BiddingUnit, exclude_bid_id=bid_id) def parse_json_fields_bid(records): diff --git a/business/views.py b/business/views.py index 146cc2d..6b6d732 100644 --- a/business/views.py +++ b/business/views.py @@ -1130,7 +1130,8 @@ class BidRegistration(APIView): # 使用统一的审核流程函数 from User.utils import create_approval_with_team_logic - content = f"项目名称:{ProjectName},申请日期:{times},招标单位:{BiddingUnit}{conflict_text}" + applicant_name = user.username if user else "" + content = f"项目名称:{ProjectName},申请日期:{times},招标单位:{BiddingUnit},申请人:{applicant_name}{conflict_text}" approval, approvers_order_json, needs_approval = create_approval_with_team_logic( team_name=team_name, @@ -1143,6 +1144,11 @@ class BidRegistration(APIView): today=formatted_date ) + # 写入申请人,便于待办列表展示及“审批完成后申请人可见” + if approval and applicant_name: + approval.applicant = applicant_name + approval.save(update_fields=['applicant']) + # 如果返回None且需要审核,说明缺少审核人 if approval is None and needs_approval: return Response({ @@ -1246,6 +1252,7 @@ class EditBid(APIView): today = datetime.datetime.now() formatted_date = today.strftime("%Y-%m-%d") team_name = None + edit_user = None token = request.META.get('token') if token: try: @@ -1254,16 +1261,21 @@ class EditBid(APIView): except User.DoesNotExist: team_name = None from User.utils import create_approval_with_team_logic + applicant_name = edit_user.username if edit_user else "" + content_edit = f"项目名称:{bid.ProjectName},申请日期:{times or bid.times},申请人:{applicant_name}" approval, approvers_order_json, needs_approval = create_approval_with_team_logic( team_name=team_name, approvers=approvers, title=bid.ProjectName + "投标登记重新编辑", - content="项目名称:" + bid.ProjectName + ",申请日期:" + (times or bid.times), + content=content_edit, approval_type="投标登记", user_id=bid.id, business_record=bid, today=formatted_date ) + 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',