From 00355e8f8bc3d7bcfccd1aff2c2bedadba39c797 Mon Sep 17 00:00:00 2001 From: ddrwode <34234@3来 34> Date: Fri, 30 Jan 2026 15:47:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=86=E6=8A=95=E6=A0=87?= =?UTF-8?q?=E5=BE=85=E5=8A=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- User/views.py | 58 +++++++++++++++++++++++++++++++++++++++++++---- business/views.py | 38 +++++++++++++++++++++++-------- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/User/views.py b/User/views.py index 3170d03..c7a5f8c 100644 --- a/User/views.py +++ b/User/views.py @@ -886,14 +886,37 @@ class roxyExhibition(APIView): except Exception: completed_bid_query = completed_bid_applicant - # 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 OR 已通过的待办查询 OR 已通过的投标登记(申请人/审批人可见) + # 立项登记审批完成后,申请人与审批人均可见 + completed_project_query = Q() + completed_project_applicant = Q(type="立项登记", state="已通过", applicant=user.username) + try: + approved_project_ids = list(Approval.objects.filter(type="立项登记", state="已通过").values_list('user_id', flat=True)) + project_ids_where_user_is_approver = [] + if approved_project_ids: + project_ids_int = [int(x) for x in approved_project_ids if str(x).isdigit()] + from business.models import ProjectRegistration + for proj in ProjectRegistration.objects.filter(id__in=project_ids_int, is_deleted=False): + try: + order = json.loads(proj.approvers_order or '[]') + if isinstance(order, list) and user.username in order: + project_ids_where_user_is_approver.append(proj.id) + except (json.JSONDecodeError, TypeError): + pass + if project_ids_where_user_is_approver: + completed_project_query = completed_project_applicant | Q(type="立项登记", state="已通过", user_id__in=[str(x) for x in project_ids_where_user_is_approver]) + else: + completed_project_query = completed_project_applicant + except Exception: + completed_project_query = completed_project_applicant + + # 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 OR 已通过的待办查询 OR 已通过的投标/立项登记(申请人/审批人可见) # 如果用户有部门,使用部门匹配;否则只使用审批员匹配 # 注意:审批员匹配必须精确匹配当前用户名,确保多人团队审核时,只有当前审核人能看到 if user_department_ids_str: - query &= (department_query | person_query | finance_query | completed_todo_query | completed_bid_query) + query &= (department_query | person_query | finance_query | completed_todo_query | completed_bid_query | completed_project_query) else: - # 如果用户没有部门,匹配审批员或财务(仅财务部人员)或已通过的待办或已通过的投标登记 - query &= (person_query | finance_query | completed_todo_query | completed_bid_query) + # 如果用户没有部门,匹配审批员或财务(仅财务部人员)或已通过的待办或已通过的投标/立项登记 + query &= (person_query | finance_query | completed_todo_query | completed_bid_query | completed_project_query) # 添加调试日志 import logging @@ -1361,8 +1384,33 @@ class roxyExhibition(APIView): settlement_salary = salary_match.group(1) itme["settlement_salary"] = settlement_salary - # 如果是立项登记类型,检索冲突信息并添加到返回字段 + # 如果是立项登记类型:返回申请人、审批流程、冲突信息等(审批人--->申请人,审批完成后申请人/审批人可见) if info.type == "立项登记": + # 申请人:优先从 Approval.applicant 取,否则从 content 解析「申请人:xxx」 + submitter_proj = getattr(info, 'applicant', None) + if not submitter_proj and content and "申请人:" in content: + import re + m = re.search(r'申请人:([^,→\s]+)', content) + if m: + submitter_proj = m.group(1).strip() + itme["submitter"] = submitter_proj or "" + itme["applicant"] = submitter_proj or "" + try: + project_id = int(info.user_id) + project = ProjectRegistration.objects.filter(id=project_id, is_deleted=False).first() + approvers_order_list_proj = [] + if project and getattr(project, 'approvers_order', None): + try: + order = json.loads(project.approvers_order or '[]') + approvers_order_list_proj = order if isinstance(order, list) else [] + except (json.JSONDecodeError, TypeError): + pass + itme["approvers_order"] = approvers_order_list_proj + content_val_proj = itme.get("content") or "" + if submitter_proj and "申请人:" not in content_val_proj and "提交人:" not in content_val_proj: + itme["content"] = content_val_proj.rstrip() + ",申请人:" + submitter_proj + except (ValueError, TypeError, AttributeError): + itme["approvers_order"] = [] try: from business.views import search_related_records diff --git a/business/views.py b/business/views.py index 8dd93b9..4f119c9 100644 --- a/business/views.py +++ b/business/views.py @@ -652,14 +652,15 @@ class Project(APIView): # 获取团队信息:优先负责人,其次当前登录用户 team_name = get_team_name_from_responsiblefor(responsiblefor_dict) - if not team_name: - token = request.META.get('token') or request.META.get('HTTP_AUTHORIZATION', '').replace('Bearer ', '') - if token: - try: - request_user = User.objects.get(token=token, is_deleted=False) + request_user = None + token = request.META.get('token') or request.META.get('HTTP_AUTHORIZATION', '').replace('Bearer ', '') + if token: + try: + request_user = User.objects.get(token=token, is_deleted=False) + if not team_name: team_name = request_user.team - except User.DoesNotExist: - pass + except User.DoesNotExist: + pass # 使用统一的审核流程函数 from User.utils import create_approval_with_team_logic @@ -686,8 +687,8 @@ class Project(APIView): conflict_parts.append(f"投标冲突:{len(related_records_info['bid_conflicts'])}条(项目:{','.join([r['ProjectName'][:20] if r['ProjectName'] else '' for r in related_records_info['bid_conflicts'][:3]])}{'...' if len(related_records_info['bid_conflicts']) > 3 else ''})") conflict_text = ";冲突记录:" + ";".join(conflict_parts) if conflict_parts else "" - - content = f"{responsiblefor_dict.get('responsible_person')}在{times}办理立项登记,项目类型:{project_type},合同编号:{ContractNo},{responsible_desc},收费情况:{charge}{conflict_text}" + applicant_name = request_user.username if request_user else "" + content = f"{responsiblefor_dict.get('responsible_person')}在{times}办理立项登记,项目类型:{project_type},合同编号:{ContractNo},{responsible_desc},收费情况:{charge},申请人:{applicant_name}{conflict_text}" approval, approvers_order_json, needs_approval = create_approval_with_team_logic( team_name=team_name, @@ -700,6 +701,11 @@ class Project(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({ @@ -982,10 +988,19 @@ class EditProject(APIView): current_responsiblefor = original_responsiblefor.get('responsible_person', '') if isinstance(original_responsiblefor, dict) else '' responsible_desc = current_responsiblefor + edit_user = None + token = request.META.get('token') or request.META.get('HTTP_AUTHORIZATION', '').replace('Bearer ', '') + if token: + try: + edit_user = User.objects.get(token=token, is_deleted=False) + except User.DoesNotExist: + pass + applicant_name = edit_user.username if edit_user else "" + from User.utils import create_approval_with_team_logic team_name = get_team_name_from_responsiblefor(responsiblefor_dict if responsiblefor else original_responsiblefor) content = current_responsiblefor + "在" + ( - times or original_times) + "办理立项登记,项目类型:" + original_type + ",合同编号:" + original_ContractNo + "描述:" + ",负责人:" + responsible_desc + ",收费情况:" + (charge or original_charge) + times or original_times) + "办理立项登记,项目类型:" + original_type + ",合同编号:" + original_ContractNo + "描述:" + ",负责人:" + responsible_desc + ",收费情况:" + (charge or original_charge) + ",申请人:" + applicant_name approval, approvers_order_json, needs_approval = create_approval_with_team_logic( team_name=team_name, approvers=approvers, @@ -996,6 +1011,9 @@ class EditProject(APIView): business_record=pro, 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',