更新了软删除

This commit is contained in:
27942
2025-12-31 12:28:10 +08:00
parent 2af30a5e33
commit 1d9bd47bac
8 changed files with 680 additions and 6 deletions

View File

@@ -0,0 +1,40 @@
# Generated migration for operation log
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('User', '0013_add_is_deleted_fields'),
]
operations = [
migrations.CreateModel(
name='OperationLog',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('operator', models.CharField(max_length=100)),
('operator_id', models.IntegerField(blank=True, null=True)),
('operation_type', models.CharField(max_length=50)),
('module', models.CharField(max_length=50)),
('action', models.CharField(max_length=200)),
('target_type', models.CharField(max_length=100)),
('target_id', models.CharField(blank=True, max_length=100, null=True)),
('target_name', models.CharField(blank=True, max_length=200, null=True)),
('old_data', models.TextField(blank=True, null=True)),
('new_data', models.TextField(blank=True, null=True)),
('ip_address', models.CharField(blank=True, max_length=50, null=True)),
('user_agent', models.CharField(blank=True, max_length=500, null=True)),
('request_path', models.CharField(blank=True, max_length=500, null=True)),
('remark', models.TextField(blank=True, null=True)),
('create_time', models.DateTimeField(auto_now_add=True)),
],
options={
'verbose_name': '操作日志',
'verbose_name_plural': '操作日志',
'db_table': 'operation_log',
'ordering': ['-create_time'],
},
),
]

View File

@@ -44,3 +44,27 @@ class Approval(models.Model):
is_deleted = models.BooleanField(default=False) # 软删除标记
class OperationLog(models.Model):
"""操作日志模型 - 记录高风险操作"""
operator = models.CharField(max_length=100) # 操作人用户名
operator_id = models.IntegerField(null=True, blank=True) # 操作人ID
operation_type = models.CharField(max_length=50) # 操作类型DELETE, CREATE, UPDATE, APPROVE等
module = models.CharField(max_length=50) # 模块User, Business, Finance等
action = models.CharField(max_length=200) # 操作描述:删除用户、创建立项等
target_type = models.CharField(max_length=100) # 目标类型User, ProjectRegistration等
target_id = models.CharField(max_length=100, null=True, blank=True) # 目标ID
target_name = models.CharField(max_length=200, null=True, blank=True) # 目标名称(如用户名、项目名等)
old_data = models.TextField(null=True, blank=True) # 操作前的数据JSON格式
new_data = models.TextField(null=True, blank=True) # 操作后的数据JSON格式
ip_address = models.CharField(max_length=50, null=True, blank=True) # IP地址
user_agent = models.CharField(max_length=500, null=True, blank=True) # 用户代理
request_path = models.CharField(max_length=500, null=True, blank=True) # 请求路径
remark = models.TextField(null=True, blank=True) # 备注
create_time = models.DateTimeField(auto_now_add=True) # 操作时间
class Meta:
db_table = 'operation_log'
ordering = ['-create_time']
verbose_name = '操作日志'
verbose_name_plural = '操作日志'

View File

@@ -1,5 +1,5 @@
from django.urls import path
from .views import CreateUserView,LoginView,EditorialStaffView,PersonnelDetailsView,DepartmentView,PersonnelListView,AddDepartment,DeleteDepartment,Personlist,roxyExhibition,approvalProcessing,personneldisplay,DeleteUser
from .views import CreateUserView,LoginView,EditorialStaffView,PersonnelDetailsView,DepartmentView,PersonnelListView,AddDepartment,DeleteDepartment,Personlist,roxyExhibition,approvalProcessing,personneldisplay,DeleteUser,OperationLogView
urlpatterns = [
path('create-user',CreateUserView.as_view(),name='create-user'),
path('login',LoginView.as_view(),name='login'),
@@ -14,4 +14,5 @@ urlpatterns = [
path('approval_processing',approvalProcessing.as_view(),name='approval_processing'),
path('personneldisplay',personneldisplay.as_view(),name='personneldisplay'),
path('deleteUser',DeleteUser.as_view(),name='deleteUser'),
path('operation-log',OperationLogView.as_view(),name='operation-log'),
]

View File

@@ -1,6 +1,9 @@
"""
审批相关的工具函数
"""
import json
from datetime import datetime
from .models import OperationLog, User
def is_department_id(value):
"""
@@ -60,3 +63,75 @@ def format_personincharge(value, is_department=False):
# 审批员用户名:保持原样,但确保是字符串
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

View File

@@ -4,7 +4,7 @@ from rest_framework.response import Response
from rest_framework import status
import json
import ast
from .models import User, Approval, Department
from .models import User, Approval, Department, OperationLog
from business.models import permission
from finance.models import Income, Accounts, Payment, Reimbursement, BonusChange
from finance.models import Invoice
@@ -15,7 +15,7 @@ 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
from .utils import is_department_id, log_operation
class CreateUserView(APIView):
@@ -157,6 +157,28 @@ class CreateUserView(APIView):
user.role.add(*role_list)
if department_id:
user.department.add(*department_id)
# 记录操作日志
new_data = {
'id': user.id,
'username': user.username,
'account': user.account,
'position': user.position,
'team': user.team,
'state': user.state
}
log_operation(
request=request,
operation_type='CREATE',
module='User',
action='新增用户',
target_type='User',
target_id=user.id,
target_name=user.username,
new_data=new_data,
remark=f'新增用户:{user.username}(账号:{user.account}'
)
return Response({'message': '添加人员成功', 'code': 0}, status=status.HTTP_200_OK)
except Exception as e:
# 捕获数据库操作异常
@@ -276,7 +298,44 @@ class EditorialStaffView(APIView):
role_id = [role_id]
user.role.set(role_id)
# 记录操作前的数据
old_data = {
'id': user.id,
'username': user.username,
'account': user.account,
'position': user.position,
'team': user.team,
'state': user.state,
'salary': user.salary
}
user.save()
# 记录操作后的数据
new_data = {
'id': user.id,
'username': user.username,
'account': user.account,
'position': user.position,
'team': user.team,
'state': user.state,
'salary': user.salary
}
# 记录操作日志
log_operation(
request=request,
operation_type='UPDATE',
module='User',
action='编辑用户信息',
target_type='User',
target_id=user.id,
target_name=user.username,
old_data=old_data,
new_data=new_data,
remark=f'编辑用户信息:{user.username}(账号:{user.account}'
)
return Response({'message': '修改成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -310,6 +369,18 @@ class LoginView(APIView):
user.token = token
user.save()
# 记录登录日志
log_operation(
request=request,
operation_type='LOGIN',
module='User',
action='用户登录',
target_type='User',
target_id=user.id,
target_name=user.username,
remark=f'用户登录:{user.username}(账号:{user.account}'
)
# 创建会话
session = SessionStore()
session.create()
@@ -505,9 +576,29 @@ class DeleteDepartment(APIView):
return Response({'status': 'error', 'message': '删除失败,该部门还存在人员,请及时转移', 'code': 1},
status=status.HTTP_400_BAD_REQUEST)
# 记录操作前的数据
old_data = {
'id': dep.id,
'username': dep.username
}
# 软删除:更新 is_deleted 字段
dep.is_deleted = True
dep.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='User',
action='删除部门',
target_type='Department',
target_id=dep.id,
target_name=dep.username,
old_data=old_data,
remark=f'删除部门:{dep.username}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -805,7 +896,121 @@ class DeleteUser(APIView):
except User.DoesNotExist:
return Response({'status': 'error', 'message': '用户不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 记录操作前的数据
old_data = {
'id': user.id,
'username': user.username,
'account': user.account,
'state': user.state,
'position': user.position,
'team': user.team
}
# 软删除:更新 is_deleted 字段
user.is_deleted = True
user.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='User',
action='删除用户',
target_type='User',
target_id=user.id,
target_name=user.username,
old_data=old_data,
remark=f'删除用户:{user.username}(账号:{user.account}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
class OperationLogView(APIView):
"""操作日志查询接口"""
def post(self, request, *args, **kwargs):
"""
查询操作日志
支持按操作人、操作类型、模块、时间范围等条件查询
"""
page = request.data.get('page', 1)
per_page = request.data.get('per_page', 20)
operator = request.data.get('operator') # 操作人
operation_type = request.data.get('operation_type') # 操作类型
module = request.data.get('module') # 模块
target_type = request.data.get('target_type') # 目标类型
start_time = request.data.get('start_time') # 开始时间
end_time = request.data.get('end_time') # 结束时间
# 构建查询条件
query = Q()
if operator:
query &= Q(operator__icontains=operator)
if operation_type:
query &= Q(operation_type=operation_type)
if module:
query &= Q(module=module)
if target_type:
query &= Q(target_type=target_type)
if start_time:
try:
start_datetime = datetime.datetime.strptime(start_time, "%Y-%m-%d")
query &= Q(create_time__gte=start_datetime)
except:
pass
if end_time:
try:
end_datetime = datetime.datetime.strptime(end_time, "%Y-%m-%d")
# 结束时间包含当天,所以加一天
end_datetime = end_datetime + datetime.timedelta(days=1)
query &= Q(create_time__lt=end_datetime)
except:
pass
# 查询日志
logs = OperationLog.objects.filter(query).order_by('-create_time')
total = logs.count()
# 分页
paginator = Paginator(logs, per_page)
try:
logs_page = paginator.page(page)
except PageNotAnInteger:
logs_page = paginator.page(1)
except EmptyPage:
logs_page = paginator.page(paginator.num_pages)
# 格式化数据
data = []
for log in logs_page.object_list:
data.append({
'id': log.id,
'operator': log.operator,
'operator_id': log.operator_id,
'operation_type': log.operation_type,
'module': log.module,
'action': log.action,
'target_type': log.target_type,
'target_id': log.target_id,
'target_name': log.target_name,
'ip_address': log.ip_address,
'request_path': log.request_path,
'remark': log.remark,
'create_time': log.create_time.strftime('%Y-%m-%d %H:%M:%S'),
'old_data': json.loads(log.old_data) if log.old_data else None,
'new_data': json.loads(log.new_data) if log.new_data else None,
})
return Response({
'message': '查询成功',
'total': total,
'data': data,
'code': 0
}, status=status.HTTP_200_OK)

View File

@@ -0,0 +1,28 @@
# Generated by Django 4.2.25 on 2025-12-31 04:26
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('business', '0025_add_is_deleted_fields'),
]
operations = [
migrations.AlterField(
model_name='bid',
name='BiddingAnnouncement',
field=models.TextField(),
),
migrations.AlterField(
model_name='projectregistration',
name='contract',
field=models.TextField(),
),
migrations.AlterField(
model_name='role',
name='permissionId',
field=models.CharField(max_length=1000),
),
]

View File

@@ -4,7 +4,7 @@ from rest_framework import status
import json
import ast
from User.models import User, Approval
from User.utils import format_personincharge
from User.utils import format_personincharge, log_operation
from .models import PreFiling, ProjectRegistration, Bid, Case, Invoice, Caselog, SealApplication, Warehousing, \
RegisterPlatform, Announcement, LawyerFlie, Schedule, permission, role
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
@@ -33,7 +33,7 @@ class registration(APIView):
if not all([times, description, Undertaker]):
return Response({'status': 'error', 'message': '缺少参数', 'code': 1}, status=status.HTTP_400_BAD_REQUEST)
PreFiling.objects.create(
prefiling = PreFiling.objects.create(
times=times,
client_username=client_username,
party_username=party_username,
@@ -41,6 +41,26 @@ class registration(APIView):
Undertaker=Undertaker,
submit=user
)
# 记录操作日志
new_data = {
'id': prefiling.id,
'client_username': prefiling.client_username,
'party_username': prefiling.party_username,
'undertaker': prefiling.Undertaker
}
log_operation(
request=request,
operation_type='CREATE',
module='Business',
action='新增预立案登记',
target_type='PreFiling',
target_id=prefiling.id,
target_name=f'{prefiling.client_username} vs {prefiling.party_username}',
new_data=new_data,
remark=f'新增预立案登记:委托人 {prefiling.client_username},相对方 {prefiling.party_username}'
)
return Response({'message': '登记成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -214,6 +234,27 @@ class Project(APIView):
type="立项登记",
user_id=pro.id
)
# 记录操作日志
new_data = {
'id': pro.id,
'contract_no': pro.ContractNo,
'type': pro.type,
'responsiblefor': pro.responsiblefor,
'times': pro.times
}
log_operation(
request=request,
operation_type='CREATE',
module='Business',
action='新增立项登记',
target_type='ProjectRegistration',
target_id=pro.id,
target_name=pro.ContractNo,
new_data=new_data,
remark=f'新增立项登记:合同编号 {pro.ContractNo},负责人 {pro.responsiblefor}'
)
return Response({'message': '登记成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -387,9 +428,29 @@ class EditProject(APIView):
pro.state = "审核中"
update_fields_list.append('state')
# 记录操作前的数据
old_data = {
'id': pro.id,
'contract_no': original_ContractNo,
'type': original_type,
'responsiblefor': original_responsiblefor,
'times': original_times,
'charge': original_charge
}
if update_fields_list:
pro.save(update_fields=update_fields_list)
# 记录操作后的数据
new_data = {
'id': pro.id,
'contract_no': pro.ContractNo,
'type': pro.type,
'responsiblefor': pro.responsiblefor,
'times': pro.times,
'charge': pro.charge
}
today = datetime.datetime.now()
formatted_date = today.strftime("%Y-%m-%d")
Approval.objects.create(
@@ -401,6 +462,20 @@ class EditProject(APIView):
type="立项登记",
user_id=pro.id
)
# 记录操作日志
log_operation(
request=request,
operation_type='UPDATE',
module='Business',
action='编辑立项登记',
target_type='ProjectRegistration',
target_id=pro.id,
target_name=pro.ContractNo,
old_data=old_data,
new_data=new_data,
remark=f'编辑立项登记:合同编号 {pro.ContractNo}'
)
return Response({'message': '编辑成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -429,9 +504,36 @@ class DeleteProject(APIView):
if case_exists:
return Response({'status': 'error', 'message': '该立项已被案件管理关联,无法删除', 'code': 1}, status=status.HTTP_400_BAD_REQUEST)
# 记录操作前的数据
try:
prefiling = PreFiling.objects.get(id=pro.user_id, is_deleted=False)
old_data = {
'id': pro.id,
'contract_no': pro.ContractNo,
'type': pro.type,
'responsiblefor': pro.responsiblefor,
'client_username': prefiling.client_username if prefiling else None
}
except:
old_data = {'id': pro.id, 'contract_no': pro.ContractNo}
# 软删除:更新 is_deleted 字段
pro.is_deleted = True
pro.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Business',
action='删除立项登记',
target_type='ProjectRegistration',
target_id=pro.id,
target_name=pro.ContractNo,
old_data=old_data,
remark=f'删除立项登记:合同编号 {pro.ContractNo}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -608,9 +710,30 @@ class DeleteBid(APIView):
except Bid.DoesNotExist:
return Response({'status': 'error', 'message': '投标登记不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 记录操作前的数据
old_data = {
'id': bid.id,
'project_name': bid.ProjectName,
'times': bid.times
}
# 软删除:更新 is_deleted 字段
bid.is_deleted = True
bid.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Business',
action='删除投标登记',
target_type='Bid',
target_id=bid.id,
target_name=bid.ProjectName,
old_data=old_data,
remark=f'删除投标登记:{bid.ProjectName}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -866,9 +989,30 @@ class DeleteCase(APIView):
except Case.DoesNotExist:
return Response({'status': 'error', 'message': '案件管理不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 记录操作前的数据
old_data = {
'id': case.id,
'times': case.times,
'state': case.state
}
# 软删除:更新 is_deleted 字段
case.is_deleted = True
case.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Business',
action='删除案件管理',
target_type='Case',
target_id=case.id,
target_name=f'案件-{case.id}',
old_data=old_data,
remark=f'删除案件管理ID {case.id}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -1888,9 +2032,27 @@ class DeleteRermission(APIView):
ID = request.data.get('id')
try:
perm = permission.objects.get(id=ID, is_deleted=False)
# 记录操作前的数据
old_data = {
'id': perm.id,
'permission_name': perm.permission_name,
'permission_logo': perm.permission_logo
}
# 软删除:更新 is_deleted 字段
perm.is_deleted = True
perm.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Business',
action='删除权限',
target_type='Permission',
target_id=perm.id,
target_name=perm.permission_name,
old_data=old_data,
remark=f'删除权限:{perm.permission_name}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
except permission.DoesNotExist:
return Response({'status': 'error', 'message': '权限不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
@@ -1938,9 +2100,27 @@ class DeleteRole(APIView):
id = request.data.get('id')
try:
r = role.objects.get(id=id, is_deleted=False)
# 记录操作前的数据
old_data = {
'id': r.id,
'role_name': r.RoleName,
'permission_id': r.permissionId
}
# 软删除:更新 is_deleted 字段
r.is_deleted = True
r.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Business',
action='删除角色',
target_type='Role',
target_id=r.id,
target_name=r.RoleName,
old_data=old_data,
remark=f'删除角色:{r.RoleName}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
except role.DoesNotExist:
return Response({'status': 'error', 'message': '角色不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)

View File

@@ -4,7 +4,7 @@ from rest_framework import status
import json
import ast
from User.models import User,Approval,Department
from User.utils import format_personincharge
from User.utils import format_personincharge, log_operation
import datetime
from .models import Invoice,Income,Accounts,Payment,Reimbursement,BonusChange
from utility.utility import flies
@@ -68,6 +68,28 @@ class UserRegister(APIView):
)
user.save(update_fields=['card', 'salary', 'username', 'Dateofjoining', 'position'])
# 记录操作日志
new_data = {
'user_id': user.id,
'username': user.username,
'card': user.card,
'position': user.position,
'salary': user.salary,
'state': user.state
}
log_operation(
request=request,
operation_type='CREATE',
module='Finance',
action='新增财务登记',
target_type='User',
target_id=user.id,
target_name=user.username,
new_data=new_data,
remark=f'新增财务登记:{user.username},岗位 {user.position},薪资 {user.salary}'
)
return Response({'message': '登记成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -117,6 +139,27 @@ class issueAnInvoice(APIView):
type="开票",
user_id = invoice.id
)
# 记录操作日志
new_data = {
'id': invoice.id,
'contract_no': invoice.ContractNo,
'amount': invoice.amount,
'type': invoice.type,
'unit': invoice.unit
}
log_operation(
request=request,
operation_type='CREATE',
module='Finance',
action='新增开票申请',
target_type='Invoice',
target_id=invoice.id,
target_name=invoice.ContractNo,
new_data=new_data,
remark=f'新增开票申请:合同号 {invoice.ContractNo},金额 {invoice.amount}'
)
return Response({'message': '提交成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -223,9 +266,42 @@ class EditInvoice(APIView):
invoice.bank = bank
update_fields_list.append('bank')
# 记录操作前的数据
old_data = {
'id': invoice.id,
'contract_no': invoice.ContractNo,
'amount': invoice.amount,
'type': invoice.type,
'unit': invoice.unit
}
if update_fields_list:
invoice.save(update_fields=update_fields_list)
# 记录操作后的数据
invoice.refresh_from_db()
new_data = {
'id': invoice.id,
'contract_no': invoice.ContractNo,
'amount': invoice.amount,
'type': invoice.type,
'unit': invoice.unit
}
# 记录操作日志
log_operation(
request=request,
operation_type='UPDATE',
module='Finance',
action='编辑开票申请',
target_type='Invoice',
target_id=invoice.id,
target_name=invoice.ContractNo,
old_data=old_data,
new_data=new_data,
remark=f'编辑开票申请:合同号 {invoice.ContractNo}'
)
return Response({'message': '编辑成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -247,9 +323,31 @@ class DeleteInvoice(APIView):
except Invoice.DoesNotExist:
return Response({'status': 'error', 'message': '开票申请不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 记录操作前的数据
old_data = {
'id': invoice.id,
'contract_no': invoice.ContractNo,
'amount': invoice.amount,
'unit': invoice.unit
}
# 软删除:更新 is_deleted 字段
invoice.is_deleted = True
invoice.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Finance',
action='删除开票申请',
target_type='Invoice',
target_id=invoice.id,
target_name=invoice.ContractNo,
old_data=old_data,
remark=f'删除开票申请:合同号 {invoice.ContractNo},金额 {invoice.amount}'
)
return Response({'message': '删除成功', 'code': 0}, status=status.HTTP_200_OK)
@@ -1329,6 +1427,15 @@ class DeleteUserDeparture(APIView):
except (User.DoesNotExist, ValueError):
return Response({'status': 'error', 'message': '用户不存在', 'code': 1}, status=status.HTTP_404_NOT_FOUND)
# 记录操作前的数据
old_data = {
'user_id': user.id,
'username': user.username,
'state': user.state,
'dateofdeparture': str(user.Dateofdeparture) if user.Dateofdeparture else None,
'approval_id': approval.id
}
# 恢复用户状态
user.state = "在职"
user.Dateofdeparture = None
@@ -1338,5 +1445,19 @@ class DeleteUserDeparture(APIView):
approval.is_deleted = True
approval.save()
# 记录操作日志
log_operation(
request=request,
operation_type='DELETE',
module='Finance',
action='删除离职登记',
target_type='Approval',
target_id=approval.id,
target_name=f'离职登记-{user.username}',
old_data=old_data,
new_data={'user_id': user.id, 'username': user.username, 'state': '在职'},
remark=f'删除离职登记,恢复用户 {user.username} 状态为"在职"'
)
return Response({'message': '删除成功,用户状态已恢复为"在职"', 'code': 0}, status=status.HTTP_200_OK)