diff --git a/User/views.py b/User/views.py index 9da84a4..abd1946 100644 --- a/User/views.py +++ b/User/views.py @@ -999,6 +999,21 @@ class approvalProcessing(APIView): user = Accounts.objects.get(id=approval.user_id, is_deleted=False) except Accounts.DoesNotExist: return Response({'status': 'error', 'message': '调账申请记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND) + + # 调账申请直接抄送财务,检查当前是否已经是财务审核 + if approval.personincharge == "财务" and approval.state == "已抄送财务": + # 财务部审核逻辑:财务部只需要一个人审核完即可完成 + if state == "已通过": + approval.state = "已通过" + user.state = "已通过" + else: + approval.state = "未通过" + user.state = "未通过" + approval.save(update_fields=['state']) + user.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) + + # 兼容旧数据:如果不是财务审核,按原逻辑处理 if state == "已通过": approval.state = "已通过" user.state = "已通过" @@ -1013,14 +1028,35 @@ class approvalProcessing(APIView): user = Payment.objects.get(id=approval.user_id, is_deleted=False) except Payment.DoesNotExist: return Response({'status': 'error', 'message': '付款申请记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND) + + # 检查当前是否已经是财务审核 + if approval.personincharge == "财务" and approval.state == "已抄送财务": + # 财务部审核逻辑:财务部只需要一个人审核完即可完成 + if state == "已通过": + approval.state = "已通过" + user.state = "已通过" + else: + approval.state = "未通过" + user.state = "未通过" + approval.save(update_fields=['state']) + user.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) + + # 审批人审核通过后,抄送财务 if state == "已通过": - approval.state = "已通过" - user.state = "已通过" + approval.personincharge = "财务" + approval.state = "已抄送财务" # 改为"已抄送财务",让财务能看到 + if "已抄送财务" not in approval.content: + approval.content = approval.content + ",审批人已通过,已抄送财务" + approval.save(update_fields=['state', 'personincharge', 'content']) + user.state = "待财务处理" + user.save(update_fields=['state']) else: + # 审批不通过 approval.state = "未通过" user.state = "未通过" - approval.save(update_fields=['state']) - user.save(update_fields=['state']) + approval.save(update_fields=['state']) + user.save(update_fields=['state']) if type == "报销申请": try: @@ -1028,6 +1064,23 @@ class approvalProcessing(APIView): except Reimbursement.DoesNotExist: return Response({'status': 'error', 'message': '报销申请记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND) + # 检查当前是否已经是财务审核 + if approval.personincharge == "财务" and approval.state == "已抄送财务": + # 财务部审核逻辑:财务部只需要一个人审核完即可完成 + if state == "已通过": + approval.state = "已通过" + reimbursement.state = "已完成" + approval.save(update_fields=['state']) + reimbursement.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) + else: + # 审批不通过 + approval.state = "未通过" + reimbursement.state = "未通过" + approval.save(update_fields=['state']) + reimbursement.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) + if state == "已通过": # 多级审批逻辑:检查是否还有下一个审批人 # personincharge字段存储所有审批人(用逗号分隔),当前审批人是第一个 @@ -1070,8 +1123,9 @@ class approvalProcessing(APIView): else: # 最后一个审批人,审批通过后抄送财务 approval.personincharge = "财务" - approval.state = "已通过" - approval.content = approval.content + ",所有审批人已通过,已抄送财务" + approval.state = "已抄送财务" # 改为"已抄送财务",让财务能看到 + if "所有审批人已通过" not in approval.content: + approval.content = approval.content + ",所有审批人已通过,已抄送财务" approval.save(update_fields=['state', 'personincharge', 'content']) reimbursement.state = "待财务处理" reimbursement.save(update_fields=['state']) diff --git a/代码实现检查报告.md b/代码实现检查报告.md new file mode 100644 index 0000000..06d6476 --- /dev/null +++ b/代码实现检查报告.md @@ -0,0 +1,190 @@ +# 待办审核功能代码实现检查报告 + +## 需求回顾 + +1. **个人团队的待办**:直接给财务部的所有人审核 +2. **多人团队的待办**: + - 可能有多人审核,而且要按照顺序审核 + - 第一个人审核完成给第二个人生成待办 + - 前端会给我多个上级,这些人一个一个审核完 + - 最后给到财务部所有人审核 +3. **财务部审核**:虽然最后都会给财务部的所有人,但是财务部只需要一个人审核完,就可以了 + +## 代码实现检查 + +### ✅ 1. 个人团队的待办直接给财务部所有人审核 + +**实现位置:** `business/views.py` - `CreateSchedule` 类(第2043-2056行) + +**代码:** +```python +if not team_name or not team or (team and team.team_type == 'personal'): + # 个人团队或无团队:直接到财务团队审核 + Approval.objects.create( + title="待办审核", + content=f"{user.username}提交了待办:{title}", + times=today, + personincharge="财务", + state="已抄送财务", + type="待办", + user_id=str(schedule.id) + ) + schedule.state = "待财务处理" + schedule.save(update_fields=['state']) +``` + +**状态:** ✅ **已实现** +- 创建审批记录时,`personincharge="财务"`,`state="已抄送财务"` +- 财务部所有人可见(通过 `roxyExhibition` 接口的查询逻辑实现) + +### ✅ 2. 多人团队按顺序审核 + +**实现位置:** +- 创建:`business/views.py` - `CreateSchedule` 类(第2058-2075行) +- 流转:`User/views.py` - `approvalProcessing` 类(第1248-1263行) + +**创建第一个审核人:** +```python +elif team and team.team_type == 'team': + # 团队类型:创建审批流程,第一个审核人 + first_approver = approvers_list[0] + Approval.objects.create( + title="待办审核", + content=content, + times=today, + personincharge=first_approver, + state="审核中", + type="待办", + user_id=str(schedule.id) + ) +``` + +**流转到下一个审核人:** +```python +# 检查是否还有下一个审批人 +if current_index < len(approvers_list) - 1: + # 还有下一个审批人,流转到下一个 + next_approver = approvers_list[current_index + 1] + approval.personincharge = next_approver + approval.state = '审核中' + # 更新 content 中的当前审批人信息 + approval.save(update_fields=['state', 'personincharge', 'content']) + schedule.state = "审核中" + schedule.save(update_fields=['state']) +``` + +**状态:** ✅ **已实现** +- 支持前端传入多个审核人(`approvers` 参数) +- 审核人顺序存储在 `Schedule.approvers_order` 字段(JSON格式) +- 当前审核人通过后,自动流转到下一个审核人 +- 更新审批记录的 `personincharge` 和 `content` 字段 + +### ✅ 3. 最后一个审核人通过后抄送财务 + +**实现位置:** `User/views.py` - `approvalProcessing` 类(第1264-1272行) + +**代码:** +```python +else: + # 最后一个审批人,审批通过后抄送财务 + approval.personincharge = "财务" + approval.state = "已抄送财务" # 改为"已抄送财务",让财务能看到 + if "所有审批人已通过" not in approval.content: + approval.content = approval.content + ",所有审批人已通过,已抄送财务" + approval.save(update_fields=['state', 'personincharge', 'content']) + schedule.state = "待财务处理" + schedule.save(update_fields=['state']) +``` + +**状态:** ✅ **已实现** +- 最后一个审核人通过后,自动将 `personincharge` 改为 `"财务"` +- 状态改为 `"已抄送财务"`,财务部所有人可见 + +### ✅ 4. 财务部只需要一个人审核完即可完成 + +**实现位置:** `User/views.py` - `approvalProcessing` 类(第1214-1219行、第1238-1243行) + +**代码:** +```python +# 个人团队直接到财务的情况 +if approval.personincharge == "财务": + approval.state = "已通过" + schedule.state = "已完成" + approval.save(update_fields=['state']) + schedule.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) + +# 多人团队最后到财务的情况 +if current_approver == "财务": + approval.state = "已通过" + schedule.state = "已完成" + approval.save(update_fields=['state']) + schedule.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) +``` + +**状态:** ✅ **已实现** +- 当 `personincharge="财务"` 时,财务部任意一人审核通过,立即标记为 `"已通过"` +- 待办状态同步更新为 `"已完成"` + +### ⚠️ 5. 财务部所有人可见的实现 + +**实现位置:** `User/views.py` - `roxyExhibition` 类(第721-730行) + +**代码:** +```python +# 财务匹配:personincharge字段是"财务",且状态为"已抄送财务" +finance_query = Q(personincharge="财务", state="已抄送财务") + +# 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 +if user_department_ids_str: + query &= (department_query | person_query | finance_query) +else: + # 如果用户没有部门,匹配审批员或财务 + query &= (person_query | finance_query) +``` + +**状态:** ⚠️ **部分实现** +- 代码逻辑上,所有用户都能看到 `personincharge="财务"` 且 `state="已抄送财务"` 的审批记录 +- **问题**:没有限制只有财务部人员才能看到这些记录 +- **可能的情况**: + 1. 系统设计就是让所有用户都能看到"已抄送财务"的记录(但只有财务部人员才能审核) + 2. 前端有额外的权限控制,限制只有财务部人员能看到 + 3. 需要通过用户的角色或部门来判断是否为财务部人员 + +**建议优化:** +如果需要限制只有财务部人员才能看到财务审核记录,可以添加权限判断: +```python +# 检查用户是否为财务部人员 +user_roles = user.role.values_list('RoleName', flat=True) +user_department_names = user.department.values_list('username', flat=True) +is_finance = ('财务部' in user_roles) or ('财务部' in user_department_names) + +# 只有财务部人员才能看到财务审核记录 +if is_finance: + finance_query = Q(personincharge="财务", state="已抄送财务") +else: + finance_query = Q() # 非财务部人员看不到财务审核记录 +``` + +## 总结 + +### ✅ 已完全实现的功能 + +1. ✅ 个人团队的待办直接给财务部所有人审核 +2. ✅ 多人团队按顺序审核(第一个人审核完成给第二个人生成待办) +3. ✅ 最后一个审核人通过后抄送财务 +4. ✅ 财务部只需要一个人审核完即可完成 + +### ⚠️ 需要确认的问题 + +1. **财务部所有人可见的实现**: + - 当前代码逻辑上,所有用户都能看到 `personincharge="财务"` 的审批记录 + - 需要确认: + - 是否前端有权限控制? + - 是否需要后端添加财务部人员判断? + - 还是系统设计就是让所有用户都能看到(但只有财务部能审核)? + +### 建议 + +如果确实需要限制只有财务部人员才能看到财务审核记录,建议在 `roxyExhibition` 接口中添加财务部人员判断逻辑。 diff --git a/审核逻辑优化总结.md b/审核逻辑优化总结.md new file mode 100644 index 0000000..0c54e82 --- /dev/null +++ b/审核逻辑优化总结.md @@ -0,0 +1,254 @@ +# 审核逻辑优化总结 + +## 优化目标 + +统一所有审批类型的审核流程,确保都遵循以下逻辑: +1. **个人团队**:直接给财务部所有人审核 +2. **多人团队**:按顺序经过多个上级审核,最后给财务部所有人审核 +3. **财务部审核**:虽然财务部所有人都能看到审批记录,但只需要一个人审核完即可完成 + +## 已优化的审批类型 + +### 1. ✅ 待办审核(已正确实现) + +**位置:** `business/views.py` - `CreateSchedule` 类,`User/views.py` - `approvalProcessing` 类 + +**逻辑:** +- 个人团队:直接创建审批记录,`personincharge="财务"`,`state="已抄送财务"` +- 多人团队:按顺序审核,最后一个审核人通过后,抄送财务 +- 财务审核:财务部任意一人审核通过后完成 + +### 2. ✅ 报销申请(已优化) + +**位置:** `finance/views.py` - `reimbursement` 类,`User/views.py` - `approvalProcessing` 类 + +**优化内容:** +1. **修复财务流转逻辑**(第1070-1078行): + - 最后一个审核人通过后,改为 `state="已抄送财务"`(之前错误地设为 `"已通过"`) + - 确保财务部能看到审批记录 + +2. **添加财务审核处理逻辑**(第1031-1044行): + - 检查当前是否已经是财务审核 + - 财务部审核通过后,`approval.state="已通过"`,`reimbursement.state="已完成"` + +**优化前的问题:** +- 最后一个审核人通过后,直接设为 `"已通过"`,财务部看不到审批记录 +- 缺少财务审核处理逻辑 + +**优化后的流程:** +``` +提交报销申请(多人团队) + ↓ +第一个审核人审核通过 + ↓ +流转到第二个审核人 + ↓ +...(依次流转) + ↓ +最后一个审核人审核通过 + ↓ +抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成(state="已通过",reimbursement.state="已完成") +``` + +### 3. ✅ 调账申请(已优化) + +**位置:** `finance/views.py` - `loan` 类,`User/views.py` - `approvalProcessing` 类 + +**优化内容:** +- 添加财务审核处理逻辑(第997-1018行) +- 调账申请直接抄送财务,财务部审核通过后完成 + +**优化后的流程:** +``` +提交调账申请 + ↓ +直接抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成(state="已通过",accounts.state="已通过") +``` + +### 4. ✅ 付款申请(已优化) + +**位置:** `finance/views.py` - `PaymentRequest` 类,`User/views.py` - `approvalProcessing` 类 + +**优化内容:** +- 优化审核逻辑(第1026-1050行) +- 审批人审核通过后,自动抄送财务 +- 添加财务审核处理逻辑 + +**优化后的流程:** +``` +提交付款申请(需要指定审批人) + ↓ +审批人审核通过 + ↓ +抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成(state="已通过",payment.state="已通过") +``` + +## 统一的审核流程规则 + +### 规则1:个人团队直接抄送财务 + +**适用场景:** +- 待办(个人团队) +- 报销申请(个人团队) +- 调账申请(所有情况) + +**流程:** +``` +提交申请 + ↓ +创建审批记录(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成 +``` + +### 规则2:多人团队按顺序审核后抄送财务 + +**适用场景:** +- 待办(多人团队) +- 报销申请(多人团队) + +**流程:** +``` +提交申请(传入多个审核人) + ↓ +第一个审核人审核通过 + ↓ +流转到第二个审核人 + ↓ +...(依次流转) + ↓ +最后一个审核人审核通过 + ↓ +抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成 +``` + +### 规则3:审批人审核后抄送财务 + +**适用场景:** +- 付款申请(需要指定审批人) + +**流程:** +``` +提交申请(需要指定审批人) + ↓ +审批人审核通过 + ↓ +抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成 +``` + +## 财务部审核统一逻辑 + +所有审批类型在财务审核时都遵循以下逻辑: + +```python +# 检查当前是否已经是财务审核 +if approval.personincharge == "财务" and approval.state == "已抄送财务": + # 财务部审核逻辑:财务部只需要一个人审核完即可完成 + if state == "已通过": + approval.state = "已通过" + # 更新对应的业务记录状态 + business_record.state = "已完成" # 或 "已通过" + else: + approval.state = "未通过" + business_record.state = "未通过" + approval.save(update_fields=['state']) + business_record.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) +``` + +## 关键修复点 + +### 1. 报销审核的财务流转逻辑 + +**修复前:** +```python +approval.state = "已通过" # ❌ 错误:财务部看不到 +``` + +**修复后:** +```python +approval.state = "已抄送财务" # ✅ 正确:财务部能看到 +``` + +### 2. 添加财务审核处理逻辑 + +所有需要财务审核的审批类型都添加了财务审核处理逻辑,确保: +- 财务部能看到审批记录(`personincharge="财务"` 且 `state="已抄送财务"`) +- 财务部任意一人审核通过后完成 +- 状态正确更新 + +## 代码修改位置 + +### User/views.py + +1. **报销申请审核逻辑**(第1025-1094行): + - 添加财务审核处理逻辑(第1031-1044行) + - 修复最后一个审核人通过后的状态(第1073行) + +2. **调账申请审核逻辑**(第997-1018行): + - 添加财务审核处理逻辑 + +3. **付款申请审核逻辑**(第1026-1050行): + - 优化审核逻辑,审批人通过后抄送财务 + - 添加财务审核处理逻辑 + +## 测试建议 + +1. **报销申请测试**: + - 测试多人团队报销申请,验证最后一个审核人通过后,财务部能看到审批记录 + - 测试财务部审核通过后,报销申请状态正确更新 + +2. **调账申请测试**: + - 测试调账申请提交后,财务部能看到审批记录 + - 测试财务部审核通过后,调账申请状态正确更新 + +3. **付款申请测试**: + - 测试审批人审核通过后,自动抄送财务 + - 测试财务部审核通过后,付款申请状态正确更新 + +## 注意事项 + +1. **状态一致性**: + - 所有审批记录在抄送财务时,必须使用 `state="已抄送财务"` + - 只有财务部审核通过后,才改为 `state="已通过"` + +2. **财务部可见性**: + - 财务部的查询条件是:`Q(personincharge="财务", state="已抄送财务")` + - 确保所有抄送财务的审批记录都符合这个条件 + +3. **业务记录状态**: + - 财务审核通过后,需要同步更新对应的业务记录状态 + - 不同业务记录的状态字段可能不同(如 `"已完成"`、`"已通过"`) + +## 总结 + +所有审批类型现在都遵循统一的审核流程: +- ✅ 个人团队直接抄送财务 +- ✅ 多人团队按顺序审核后抄送财务 +- ✅ 财务部只需要一个人审核完即可完成 +- ✅ 所有审批记录在抄送财务时使用 `state="已抄送财务"` +- ✅ 所有审批类型都有财务审核处理逻辑 + +优化已完成,所有审批类型的审核流程已统一。 diff --git a/待办审核逻辑说明.md b/待办审核逻辑说明.md new file mode 100644 index 0000000..9eaefba --- /dev/null +++ b/待办审核逻辑说明.md @@ -0,0 +1,261 @@ +# 待办审核逻辑说明 + +## 概述 + +待办审核系统根据团队类型采用不同的审核流程: +- **个人团队**:直接给财务部所有人审核 +- **多人团队**:按顺序经过多个上级审核,最后给财务部所有人审核 + +## 审核流程 + +### 1. 个人团队的待办审核 + +**流程:** +``` +提交待办 + ↓ +直接创建审批记录(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成(state="已通过",schedule.state="已完成") +``` + +**代码位置:** +- 创建逻辑:`business/views.py` - `CreateSchedule` 类(第2043-2056行) +- 审核逻辑:`User/views.py` - `approvalProcessing` 类(第1211-1219行) + +**关键点:** +- 个人团队或无团队的待办,直接创建审批记录,`personincharge="财务"` +- 状态设置为 `"已抄送财务"`,财务部所有人可见 +- 财务部任意一人审核通过后,审批状态变为 `"已通过"`,待办状态变为 `"已完成"` + +### 2. 多人团队的待办审核 + +**流程:** +``` +提交待办(前端传入多个上级审核人) + ↓ +创建审批记录(personincharge=第一个审核人,state="审核中") + ↓ +第一个审核人审核通过 + ↓ +流转到第二个审核人(personincharge=第二个审核人,state="审核中") + ↓ +...(依次流转) + ↓ +最后一个审核人审核通过 + ↓ +抄送财务(personincharge="财务",state="已抄送财务") + ↓ +财务部所有人可见 + ↓ +财务部任意一人审核通过 → 完成(state="已通过",schedule.state="已完成") +``` + +**代码位置:** +- 创建逻辑:`business/views.py` - `CreateSchedule` 类(第2058-2075行) +- 审核逻辑:`User/views.py` - `approvalProcessing` 类(第1184-1272行) + +**关键点:** +- 多人团队需要前端传入 `approvers` 参数(审核人列表) +- 审核人顺序存储在 `Schedule.approvers_order` 字段(JSON格式) +- 按顺序流转:当前审核人通过后,自动流转到下一个审核人 +- 最后一个审核人通过后,自动抄送财务 +- 财务部任意一人审核通过后,审批状态变为 `"已通过"`,待办状态变为 `"已完成"` + +## 数据模型 + +### Schedule 模型(待办) +```python +class Schedule(models.Model): + title = models.CharField(max_length=100) # 标题 + tiems = models.CharField(max_length=100) + end_time = models.CharField(max_length=100) + remark = models.CharField(max_length=200) # 备注 + state = models.CharField(max_length=100) # 状态:未完成、审核中、待财务处理、已完成、未通过 + submit = models.CharField(max_length=100, null=True, blank=True) # 提交人 + approvers_order = models.TextField(null=True, blank=True) # 审核人顺序(JSON格式) + is_deleted = models.BooleanField(default=False) +``` + +**状态说明:** +- `"未完成"`:初始状态 +- `"审核中"`:正在上级审核流程中 +- `"待财务处理"`:已抄送财务,等待财务审核 +- `"已完成"`:财务审核通过,待办完成 +- `"未通过"`:审核被拒绝 + +### Approval 模型(审批记录) +```python +class Approval(models.Model): + title = models.CharField(max_length=100) + content = models.TextField() # 内容 + times = models.DateField() # 提交时间 + personincharge = models.CharField(max_length=100) # 负责人/审批部门 + state = models.CharField(max_length=100) # 状态 + type = models.CharField(max_length=100) # 类别("待办") + user_id = models.CharField(max_length=100) # 关联的Schedule ID + is_deleted = models.BooleanField(default=False) +``` + +**personincharge 字段说明:** +- `"财务"`:表示财务部门,财务部所有人可见 +- 用户名(如 `"张三"`):表示具体审核人,只有该用户可见 + +**state 状态说明:** +- `"审核中"`:正在审核流程中 +- `"已抄送财务"`:已抄送财务,财务部所有人可见 +- `"已通过"`:审核通过,待办完成 +- `"未通过"`:审核被拒绝 + +## 接口说明 + +### 1. 创建待办接口 + +**URL:** `/business/createSchedule` + +**方法:** POST + +**请求参数:** +```json +{ + "title": "待办标题", + "tiems": "2024-01-15", + "end_time": "2024-01-20", + "remark": "备注信息", + "approvers": ["张三", "李四", "王五"] // 可选,多人团队时需要 +} +``` + +**说明:** +- `approvers` 参数: + - 可以是数组格式:`["张三", "李四", "王五"]`(推荐) + - 可以是逗号分隔的字符串:`"张三,李四,王五"` + - 个人团队不需要此参数 + - 多人团队如果不传,则使用团队配置的审核人 + +**响应示例:** +```json +{ + "message": "添加成功,已直接抄送财务", // 或个人团队 + "code": 0 +} +``` + +### 2. 审核处理接口 + +**URL:** `/User/approvalProcessing` + +**方法:** POST + +**请求参数:** +```json +{ + "state": "已通过", // 或 "未通过" + "type": "待办", + "id": 123 // Approval记录的ID +} +``` + +**审核流程:** + +#### 个人团队审核流程 +1. 如果 `personincharge="财务"` 且 `state="已抄送财务"`: + - 审核通过:`approval.state="已通过"`,`schedule.state="已完成"` + - 审核不通过:`approval.state="未通过"`,`schedule.state="未通过"` + +#### 多人团队审核流程 +1. 从 `Schedule.approvers_order` 获取审核人列表 +2. 找到当前审核人在列表中的位置 +3. 如果还有下一个审核人: + - 流转到下一个审核人:`personincharge=下一个审核人`,`state="审核中"` +4. 如果是最后一个审核人: + - 抄送财务:`personincharge="财务"`,`state="已抄送财务"` +5. 如果当前是财务审核: + - 审核通过:`approval.state="已通过"`,`schedule.state="已完成"` + - 审核不通过:`approval.state="未通过"`,`schedule.state="未通过"` + +## 财务部审核特殊逻辑 + +**重要规则:** +- 虽然审批记录会抄送给财务部所有人(`personincharge="财务"`),但**财务部只需要一个人审核完即可完成** +- 当 `personincharge="财务"` 且 `state="已抄送财务"` 时,财务部所有人可见 +- 财务部任意一人审核通过后,审批状态立即变为 `"已通过"`,待办状态变为 `"已完成"` +- 其他财务部人员看到的状态也会更新为 `"已通过"` + +**代码实现:** +```python +# User/views.py - approvalProcessing 类 +if approval.personincharge == "财务": + approval.state = "已通过" + schedule.state = "已完成" + approval.save(update_fields=['state']) + schedule.save(update_fields=['state']) +``` + +## 流程图 + +### 个人团队流程 +``` +[提交待办] + ↓ +[创建审批记录] + personincharge="财务" + state="已抄送财务" + ↓ +[财务部所有人可见] + ↓ +[财务部任意一人审核] + ↓ +[审核通过] → state="已通过" → schedule.state="已完成" +[审核不通过] → state="未通过" → schedule.state="未通过" +``` + +### 多人团队流程 +``` +[提交待办(传入多个审核人)] + ↓ +[创建审批记录] + personincharge=第一个审核人 + state="审核中" + ↓ +[第一个审核人审核] + ↓ +[审核通过] → 流转到第二个审核人 +[审核不通过] → state="未通过" + ↓ +[第二个审核人审核] + ↓ +[审核通过] → 流转到下一个审核人 +[审核不通过] → state="未通过" + ↓ +...(依次流转) + ↓ +[最后一个审核人审核] + ↓ +[审核通过] → 抄送财务 + personincharge="财务" + state="已抄送财务" + ↓ +[财务部所有人可见] + ↓ +[财务部任意一人审核] + ↓ +[审核通过] → state="已通过" → schedule.state="已完成" +[审核不通过] → state="未通过" → schedule.state="未通过" +``` + +## 注意事项 + +1. **审核人顺序**:多人团队的审核人顺序由前端传入的 `approvers` 参数决定,存储在 `Schedule.approvers_order` 字段中 +2. **财务部审核**:虽然财务部所有人都能看到审批记录,但只需要一个人审核通过即可完成 +3. **状态同步**:审批记录的状态和待办记录的状态会同步更新 +4. **兼容性**:代码支持从 `Schedule.approvers_order` 字段读取审核人顺序,也兼容从 `Approval.content` 字段解析(旧数据) + +## 相关文件 + +- `business/views.py` - `CreateSchedule` 类:创建待办和审批记录 +- `User/views.py` - `approvalProcessing` 类:处理审核逻辑 +- `business/models.py` - `Schedule` 模型:待办数据模型 +- `User/models.py` - `Approval` 模型:审批记录数据模型 diff --git a/项目逻辑冲突分析报告.md b/项目逻辑冲突分析报告.md new file mode 100644 index 0000000..053270e --- /dev/null +++ b/项目逻辑冲突分析报告.md @@ -0,0 +1,239 @@ +# 项目逻辑冲突分析报告 + +## 🔴 严重冲突:报销审核与待办审核的财务流转逻辑不一致 + +### 冲突描述 + +**报销审核**(`User/views.py` 第1070-1077行): +```python +else: + # 最后一个审批人,审批通过后抄送财务 + approval.personincharge = "财务" + approval.state = "已通过" # ❌ 直接设为"已通过" + approval.content = approval.content + ",所有审批人已通过,已抄送财务" + approval.save(update_fields=['state', 'personincharge', 'content']) + reimbursement.state = "待财务处理" + reimbursement.save(update_fields=['state']) +``` + +**待办审核**(`User/views.py` 第1264-1272行): +```python +else: + # 最后一个审批人,审批通过后抄送财务 + approval.personincharge = "财务" + approval.state = "已抄送财务" # ✅ 设为"已抄送财务",让财务能看到 + if "所有审批人已通过" not in approval.content: + approval.content = approval.content + ",所有审批人已通过,已抄送财务" + approval.save(update_fields=['state', 'personincharge', 'content']) + schedule.state = "待财务处理" + schedule.save(update_fields=['state']) +``` + +### 问题分析 + +1. **报销审核的问题**: + - 最后一个审核人通过后,`approval.state` 直接设为 `"已通过"` + - 但财务部的查询条件是:`Q(personincharge="财务", state="已抄送财务")`(第722行) + - **结果**:财务部看不到这个审批记录,无法审核! + +2. **待办审核的逻辑**: + - 最后一个审核人通过后,`approval.state` 设为 `"已抄送财务"` + - 财务部可以看到并审核 + - 财务部审核通过后,才改为 `"已通过"` + +### 影响范围 + +- **报销申请**:最后一个审核人通过后,财务部无法看到审批记录,无法进行财务审核 +- **数据一致性**:报销和待办的审核流程不一致,容易造成混淆 + +### 修复建议 + +**方案1:统一为待办审核的逻辑(推荐)** +```python +# User/views.py - 报销审核部分(第1070-1077行) +else: + # 最后一个审批人,审批通过后抄送财务 + approval.personincharge = "财务" + approval.state = "已抄送财务" # 改为"已抄送财务",让财务能看到 + approval.content = approval.content + ",所有审批人已通过,已抄送财务" + approval.save(update_fields=['state', 'personincharge', 'content']) + reimbursement.state = "待财务处理" + reimbursement.save(update_fields=['state']) +``` + +**方案2:添加财务审核处理逻辑** +需要在报销审核的财务审核部分添加处理逻辑(类似待办审核的第1214-1219行): +```python +# 在报销审核的财务审核部分添加 +if approval.personincharge == "财务" and approval.state == "已抄送财务": + approval.state = "已通过" + reimbursement.state = "已完成" # 或根据业务需求设置 + approval.save(update_fields=['state']) + reimbursement.save(update_fields=['state']) +``` + +--- + +## ⚠️ 潜在问题:财务部审核权限判断缺失 + +### 问题描述 + +在 `User/views.py` 的 `roxyExhibition` 接口(第721-730行)中: +```python +# 财务匹配:personincharge字段是"财务",且状态为"已抄送财务" +finance_query = Q(personincharge="财务", state="已抄送财务") + +# 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配 +if user_department_ids_str: + query &= (department_query | person_query | finance_query) +else: + # 如果用户没有部门,匹配审批员或财务 + query &= (person_query | finance_query) +``` + +### 问题分析 + +- **所有用户都能看到** `personincharge="财务"` 且 `state="已抄送财务"` 的审批记录 +- 没有判断用户是否为财务部人员 +- 可能导致非财务人员也能看到财务审核记录 + +### 影响 + +- 数据安全性:非财务人员可能看到财务审核记录 +- 业务逻辑:不符合"财务部所有人可见"的需求(应该是"只有财务部人员可见") + +### 修复建议 + +```python +# 检查用户是否为财务部人员 +user_roles = user.role.values_list('RoleName', flat=True) +user_department_names = user.department.values_list('username', flat=True) +is_finance = ('财务部' in user_roles) or ('财务部' in user_department_names) + +# 只有财务部人员才能看到财务审核记录 +if is_finance: + finance_query = Q(personincharge="财务", state="已抄送财务") +else: + finance_query = Q() # 非财务部人员看不到财务审核记录 +``` + +--- + +## ⚠️ 潜在问题:报销审核缺少审核人顺序存储 + +### 问题描述 + +**待办审核**: +- 使用 `Schedule.approvers_order` 字段(JSON格式)存储审核人顺序 +- 审核时从该字段读取审核人列表 + +**报销审核**: +- 没有类似的字段存储审核人顺序 +- 审核时从 `Approval.content` 字段解析审核人列表(第1036-1046行) +- 依赖 content 字段的格式,不够可靠 + +### 问题分析 + +1. **数据存储不一致**: + - 待办:使用专门的字段存储审核人顺序 + - 报销:依赖 content 字段解析 + +2. **解析风险**: + - 如果 content 格式变化,解析可能失败 + - 代码中有多处 try-except,说明解析可能失败 + +### 影响 + +- 如果 content 格式不正确,可能导致审核流程中断 +- 数据迁移或格式变更时,可能出现问题 + +### 修复建议 + +**方案1:为 Reimbursement 模型添加 approvers_order 字段(推荐)** +```python +# finance/models.py +class Reimbursement(models.Model): + # ... 现有字段 ... + approvers_order = models.TextField(null=True, blank=True) # 审核人顺序(JSON格式) +``` + +**方案2:统一使用 content 解析(不推荐)** +- 待办审核也改为从 content 解析 +- 但这样会降低数据可靠性 + +--- + +## ⚠️ 潜在问题:状态流转不一致 + +### 问题描述 + +**待办审核**: +- 个人团队:`state="已抄送财务"` → 财务审核 → `state="已通过"` +- 多人团队:`state="审核中"` → ... → `state="已抄送财务"` → 财务审核 → `state="已通过"` + +**报销审核**: +- 个人团队:`state="已抄送财务"` → 财务审核 → `state="已通过"`(但缺少财务审核处理逻辑) +- 多人团队:`state="审核中"` → ... → `state="已通过"`(❌ 直接设为已通过,财务看不到) + +### 问题分析 + +1. **报销审核缺少财务审核处理逻辑**: + - 待办审核有明确的财务审核处理(第1214-1219行、第1238-1243行) + - 报销审核没有对应的财务审核处理逻辑 + +2. **状态流转不完整**: + - 报销审核在最后一个审核人通过后,直接设为"已通过" + - 跳过了财务审核环节 + +### 修复建议 + +在报销审核的财务审核部分添加处理逻辑: +```python +# User/views.py - approvalProcessing 类 +if type == "报销申请": + # ... 现有代码 ... + + # 添加财务审核处理逻辑 + if approval.personincharge == "财务" and approval.state == "已抄送财务": + if state == "已通过": + approval.state = "已通过" + reimbursement.state = "已完成" # 或根据业务需求设置 + else: + approval.state = "未通过" + reimbursement.state = "未通过" + approval.save(update_fields=['state']) + reimbursement.save(update_fields=['state']) + return Response({'message': '处理成功', 'code': 0}, status=status.HTTP_200_OK) +``` + +--- + +## 📋 总结 + +### 严重冲突(必须修复) + +1. **报销审核财务流转逻辑错误**: + - 最后一个审核人通过后,直接设为"已通过" + - 财务部无法看到审批记录 + - **修复优先级:🔴 高** + +### 潜在问题(建议修复) + +2. **财务部审核权限判断缺失**: + - 所有用户都能看到财务审核记录 + - **修复优先级:🟡 中** + +3. **报销审核缺少审核人顺序存储**: + - 依赖 content 字段解析,不够可靠 + - **修复优先级:🟡 中** + +4. **报销审核缺少财务审核处理逻辑**: + - 没有明确的财务审核处理 + - **修复优先级:🟡 中** + +### 建议修复顺序 + +1. **首先修复**:报销审核的财务流转逻辑(第1073行) +2. **其次修复**:添加报销审核的财务审核处理逻辑 +3. **然后优化**:添加财务部权限判断 +4. **最后优化**:为报销添加审核人顺序存储字段