138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
"""
|
||
审批相关的工具函数
|
||
"""
|
||
import json
|
||
from datetime import datetime
|
||
from .models import OperationLog, User
|
||
|
||
def is_department_id(value):
|
||
"""
|
||
判断personincharge字段的值是部门ID还是审批员用户名
|
||
|
||
统一规则:
|
||
- 如果是纯数字字符串(如 "1", "2", "123"),表示部门ID
|
||
- 如果包含非数字字符(如 "张三", "李四"),表示审批员用户名
|
||
|
||
Args:
|
||
value: personincharge字段的值(字符串)
|
||
|
||
Returns:
|
||
bool: True表示是部门ID,False表示是审批员用户名
|
||
|
||
示例:
|
||
>>> is_department_id("1")
|
||
True
|
||
>>> is_department_id("123")
|
||
True
|
||
>>> is_department_id("张三")
|
||
False
|
||
>>> is_department_id("dept:1")
|
||
False
|
||
"""
|
||
if not value:
|
||
return False
|
||
# 判断是否为纯数字字符串(去除首尾空格)
|
||
return str(value).strip().isdigit()
|
||
|
||
|
||
def format_personincharge(value, is_department=False):
|
||
"""
|
||
格式化personincharge字段的值
|
||
|
||
统一规则:
|
||
- 如果是部门ID,确保是纯数字字符串
|
||
- 如果是审批员用户名,保持原样
|
||
|
||
Args:
|
||
value: 部门ID(整数或字符串)或审批员用户名(字符串)
|
||
is_department: 是否为部门ID,默认False(审批员用户名)
|
||
|
||
Returns:
|
||
str: 格式化后的personincharge值
|
||
"""
|
||
if not value:
|
||
return ''
|
||
|
||
if is_department:
|
||
# 部门ID:转换为字符串,确保是纯数字
|
||
try:
|
||
return str(int(value))
|
||
except (ValueError, TypeError):
|
||
raise ValueError(f"部门ID必须是数字,当前值: {value}")
|
||
else:
|
||
# 审批员用户名:保持原样,但确保是字符串
|
||
return str(value).strip()
|
||
|
||
|
||
def log_operation(request, operation_type, module, action, target_type, target_id=None,
|
||
target_name=None, old_data=None, new_data=None, remark=None):
|
||
"""
|
||
记录操作日志
|
||
|
||
Args:
|
||
request: Django request对象
|
||
operation_type: 操作类型(DELETE, CREATE, UPDATE, APPROVE等)
|
||
module: 模块名称(User, Business, Finance等)
|
||
action: 操作描述(如"删除用户"、"创建立项"等)
|
||
target_type: 目标类型(如User, ProjectRegistration等)
|
||
target_id: 目标ID
|
||
target_name: 目标名称(如用户名、项目名等)
|
||
old_data: 操作前的数据(字典,会自动转换为JSON)
|
||
new_data: 操作后的数据(字典,会自动转换为JSON)
|
||
remark: 备注信息
|
||
|
||
Returns:
|
||
OperationLog对象
|
||
"""
|
||
try:
|
||
# 获取操作人信息
|
||
token = request.META.get('token') or request.META.get('HTTP_AUTHORIZATION', '').replace('Bearer ', '')
|
||
operator = '未知用户'
|
||
operator_id = None
|
||
|
||
if token:
|
||
try:
|
||
user = User.objects.get(token=token, is_deleted=False)
|
||
operator = user.username
|
||
operator_id = user.id
|
||
except User.DoesNotExist:
|
||
pass
|
||
|
||
# 获取IP地址
|
||
ip_address = request.META.get('HTTP_X_FORWARDED_FOR', '').split(',')[0].strip()
|
||
if not ip_address:
|
||
ip_address = request.META.get('REMOTE_ADDR', '')
|
||
|
||
# 获取用户代理
|
||
user_agent = request.META.get('HTTP_USER_AGENT', '')
|
||
|
||
# 转换数据为JSON字符串
|
||
old_data_str = json.dumps(old_data, ensure_ascii=False) if old_data else None
|
||
new_data_str = json.dumps(new_data, ensure_ascii=False) if new_data else None
|
||
|
||
# 创建日志记录
|
||
log = OperationLog.objects.create(
|
||
operator=operator,
|
||
operator_id=operator_id,
|
||
operation_type=operation_type,
|
||
module=module,
|
||
action=action,
|
||
target_type=target_type,
|
||
target_id=str(target_id) if target_id else None,
|
||
target_name=target_name,
|
||
old_data=old_data_str,
|
||
new_data=new_data_str,
|
||
ip_address=ip_address,
|
||
user_agent=user_agent,
|
||
request_path=request.path,
|
||
remark=remark
|
||
)
|
||
return log
|
||
except Exception as e:
|
||
# 日志记录失败不应该影响主业务流程
|
||
import logging
|
||
logger = logging.getLogger(__name__)
|
||
logger.error(f"记录操作日志失败: {str(e)}")
|
||
return None
|
||
|