This commit is contained in:
ddrwode
2026-01-15 18:06:41 +08:00
parent 7eca56cb35
commit d8559b4e33
3 changed files with 107 additions and 33 deletions

View File

@@ -3,7 +3,7 @@
"""
import json
from datetime import datetime
from .models import OperationLog, User, Team, Approval
from .models import OperationLog, User, Team, Approval, Department
def is_department_id(value):
"""
@@ -64,6 +64,50 @@ def format_personincharge(value, is_department=False):
return str(value).strip()
def get_finance_personincharge_candidates():
"""
获取财务部抄送的负责人标识列表优先使用部门ID其次回退字符串“财务”。
返回按优先级去重的字符串列表,便于 personincharge 匹配和查询。
"""
candidates = []
try:
finance_dept_ids = Department.objects.filter(
is_deleted=False,
username__icontains="财务"
).values_list("id", flat=True)
candidates.extend([str(dept_id) for dept_id in finance_dept_ids])
except Exception:
pass
# 回退保留原有字符串标识,兼容历史数据
candidates.append("财务")
# 去重保持顺序
uniq = []
seen = set()
for item in candidates:
if item is None:
continue
item_str = str(item)
if item_str not in seen:
uniq.append(item_str)
seen.add(item_str)
return uniq
def get_finance_personincharge_value():
"""获取优先的财务抄送标识(用于写入 personincharge"""
candidates = get_finance_personincharge_candidates()
return candidates[0] if candidates else "财务"
def is_finance_personincharge(value):
"""判断 personincharge 是否表示财务部门抄送部门ID或“财务”字符串"""
if value is None:
return False
return str(value) in get_finance_personincharge_candidates()
def log_operation(request, operation_type, module, action, target_type, target_id=None,
target_name=None, old_data=None, new_data=None, remark=None):
"""
@@ -517,8 +561,8 @@ def process_approval_flow(approval, business_record, current_approver, state,
return True, None
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
# 检查当前是否已经是财务审核部门ID或“财务”字符串均视为财务阶段
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -540,11 +584,12 @@ def process_approval_flow(approval, business_record, current_approver, state,
if not approvers_list:
# 没有审核人列表(个人团队或直接到财务)
# 如果当前不是财务,则抄送财务
if approval.personincharge != "财务":
approval.personincharge = "财务"
if not is_finance_personincharge(approval.personincharge):
finance_personincharge = get_finance_personincharge_value()
approval.personincharge = finance_personincharge
approval.state = "已抄送财务"
if "已抄送财务" not in approval.content:
approval.content = approval.content + ",已抄送财务"
if "已抄送财务" not in approval.content and "已抄送财务部" not in approval.content:
approval.content = approval.content + ",已抄送财务"
approval.save(update_fields=['state', 'personincharge', 'content'])
if business_record and hasattr(business_record, 'state'):
@@ -583,17 +628,18 @@ def process_approval_flow(approval, business_record, current_approver, state,
else:
# 最后一个审核人,抄送财务
logger.info(f"process_approval_flow: 最后一个审核人已审核,流转到财务部")
approval.personincharge = "财务"
finance_personincharge = get_finance_personincharge_value()
approval.personincharge = finance_personincharge
approval.state = "已抄送财务"
if "已抄送财务" not in approval.content:
approval.content = approval.content + ",已抄送财务"
if "已抄送财务" not in approval.content and "已抄送财务部" not in approval.content:
approval.content = approval.content + ",已抄送财务"
approval.save(update_fields=['state', 'personincharge', 'content'])
if business_record and hasattr(business_record, 'state'):
business_record.state = "待财务处理"
business_record.save(update_fields=['state'])
logger.info(f"process_approval_flow: 已抄送财务部personincharge=财务, state=已抄送财务")
logger.info(f"process_approval_flow: 已抄送财务部personincharge=%s, state=已抄送财务", approval.personincharge)
return False, None
@@ -641,11 +687,16 @@ 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'):
# 个人团队或无团队:直接到财务团队审核
finance_personincharge = get_finance_personincharge_value()
content_to_save = content
if "已抄送财务" not in content and "已抄送财务部" not in content:
content_to_save = content + ",已抄送财务部"
approval = Approval.objects.create(
title=title,
content=content,
content=content_to_save,
times=today,
personincharge="财务",
personincharge=finance_personincharge,
state="已抄送财务",
type=approval_type,
user_id=str(user_id)
@@ -698,7 +749,7 @@ 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}"
content_with_flow = f"{content},审批流程:{approvers_str} → 财务(按顺序审批),当前审批人:{first_approver}"
import logging
logger = logging.getLogger(__name__)
@@ -720,11 +771,16 @@ def create_approval_with_team_logic(team_name, approvers, title, content, approv
else:
# 找不到团队或团队类型未知,直接抄送财务
finance_personincharge = get_finance_personincharge_value()
content_to_save = content
if "已抄送财务" not in content and "已抄送财务部" not in content:
content_to_save = content + ",已抄送财务部"
approval = Approval.objects.create(
title=title,
content=content,
content=content_to_save,
times=today,
personincharge="财务",
personincharge=finance_personincharge,
state="已抄送财务",
type=approval_type,
user_id=str(user_id)

View File

@@ -15,7 +15,13 @@ from django.contrib.sessions.backends.db import SessionStore
from django.db.models import Count, Q
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from collections import defaultdict
from .utils import is_department_id, log_operation, get_approvers_from_record
from .utils import (
is_department_id,
log_operation,
get_approvers_from_record,
is_finance_personincharge,
get_finance_personincharge_candidates,
)
class CreateUserView(APIView):
@@ -748,6 +754,7 @@ class roxyExhibition(APIView):
# 判断用户是否是财务部人员:只通过部门名称判断
is_finance_user = '财务部' in user_department_names
finance_personincharge_candidates = get_finance_personincharge_candidates()
# 构建查询条件:
# personincharge字段统一规则
@@ -772,7 +779,7 @@ class roxyExhibition(APIView):
# 重要:只有财务部人员才能看到财务审核的审批记录
finance_query = Q()
if is_finance_user:
finance_query = Q(personincharge="财务", state="已抄送财务")
finance_query = Q(personincharge__in=finance_personincharge_candidates, state="已抄送财务")
# 组合查询:部门匹配 OR 审批员匹配 OR 财务匹配(仅财务部人员)
# 如果用户有部门,使用部门匹配;否则只使用审批员匹配
@@ -788,7 +795,11 @@ class roxyExhibition(APIView):
logger = logging.getLogger(__name__)
logger.info(f"roxyExhibition: 用户={user.username}, 部门IDs={user_department_ids_str}, 部门名称={user_department_names}")
logger.info(f"roxyExhibition: 是否是财务部人员={is_finance_user} (仅通过部门名称判断)")
logger.info(f"roxyExhibition: 查询条件 - personincharge={user.username} OR personincharge=财务(已抄送财务,仅财务部) OR personincharge IN {user_department_ids_str}")
logger.info(
f"roxyExhibition: 查询条件 - personincharge={user.username} "
f"OR personincharge in 财务标识{finance_personincharge_candidates}(已抄送财务,仅财务部) "
f"OR personincharge IN {user_department_ids_str}"
)
approvals = Approval.objects.filter(query, is_deleted=False).order_by('-id')
@@ -1030,7 +1041,7 @@ class approvalProcessing(APIView):
return Response({'status': 'error', 'message': '用户记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -1095,7 +1106,7 @@ class approvalProcessing(APIView):
return Response({'status': 'error', 'message': '收入确认记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -1143,7 +1154,7 @@ class approvalProcessing(APIView):
return Response({'status': 'error', 'message': '调账申请记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 调账申请直接抄送财务,检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -1292,7 +1303,7 @@ class approvalProcessing(APIView):
return Response({'status': 'error', 'message': '案件记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -1383,7 +1394,7 @@ class approvalProcessing(APIView):
return Response({'status': 'error', 'message': '用印申请记录不存在或已被删除', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"
@@ -1437,7 +1448,7 @@ class approvalProcessing(APIView):
approval.save(update_fields=['content'])
# 检查当前是否已经是财务审核
if approval.personincharge == "财务" and approval.state == "已抄送财务":
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
# 财务部审核逻辑:财务部只需要一个人审核完即可完成
if state == "已通过":
approval.state = "已通过"

View File

@@ -20,9 +20,9 @@
#### 2.1 个人团队流程
```python
# 个人团队:直接抄送财务
# 个人团队:直接抄送财务优先使用部门ID回退“财务”
approval = Approval.objects.create(
personincharge="财务",
personincharge="<财务部部门ID或'财务'>",
state="已抄送财务",
type="立项登记",
user_id=项目ID
@@ -40,7 +40,7 @@ approval = Approval.objects.create(
approval = Approval.objects.create(
personincharge=第一个审核人,
state="审核中",
content="审批流程:张三 → 李四 → 王五 → 财务(按顺序审批),当前审批人:张三"
content="审批流程:张三 → 李四 → 王五 → 财务(按顺序审批),当前审批人:张三"
)
# 项目状态:审核中
```
@@ -106,6 +106,12 @@ approval = Approval.objects.create(
2. 如果未传入,从团队配置中获取审核人(`team.approvers`
3. 如果团队没有配置审核人,返回错误
### 4. 财务抄送(全员)
- 财务阶段 `state="已抄送财务"``personincharge` 优先写入部门表中 `username` 包含“财务”的部门ID字符串未找到时回退 `"财务"`。
- 代办查询支持 `personincharge` 为财务部门ID或 `"财务"`,保证财务部全员可见。
- 审批内容会附加“已抄送财务部”提示,流程文案展示“财务部”节点。
## 四、立项编辑流程EditProject类
### 1. 编辑步骤
@@ -159,7 +165,8 @@ if state == "未通过":
#### 2.2 财务审核
```python
if approval.personincharge == "财务" and approval.state == "已抄送财务":
# personincharge 为财务部部门ID或 "财务"state "已抄送财务"
if is_finance_personincharge(approval.personincharge) and approval.state == "已抄送财务":
if state == "已通过":
approval.state = "已通过"
project.state = "已通过"
@@ -190,8 +197,8 @@ if approval.personincharge == "财务" and approval.state == "已抄送财务":
approval.state = "审核中"
# 更新审批内容中的当前审批人
else:
# 最后一个审核人,抄送财务
approval.personincharge = "财务"
# 最后一个审核人,抄送财务部门ID或"财务"
approval.personincharge = <财务部部门ID或"财务">
approval.state = "已抄送财务"
project.state = "待财务处理"
```
@@ -332,7 +339,7 @@ Approval (审批记录)
### 示例1个人团队
1. 创建立项:负责人属于个人团队
2. 直接创建审批记录:`personincharge="财务"`, `state="已抄送财务"`
2. 直接创建审批记录:`personincharge="<财务部部门ID或'财务'>"`, `state="已抄送财务"`
3. 项目状态:`state="待财务处理"`
4. 财务审核通过:项目状态变为 `"已通过"`
@@ -350,7 +357,7 @@ Approval (审批记录)
- `personincharge="王五"`(流转到下一个)
- `state="审核中"`
5. 王五审核通过:
- `personincharge="财务"`(最后一个,抄送财务)
- `personincharge="<财务部部门ID或'财务'>"`(最后一个,抄送财务部全员
- `state="已抄送财务"`
- 项目状态:`state="待财务处理"`
6. 财务审核通过:项目状态变为 `"已通过"`