统一记录后台敏感操作到 xiugaijilu,并提供管理员操作日志查询接口。
覆盖商家/管事/组长资金与封禁、冻结解冻、后台账号变更;列表接口权限 000001。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
127
houtai/caozuo_rizhi_views.py
Normal file
127
houtai/caozuo_rizhi_views.py
Normal file
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
后台操作日志查询(管理员管理页,权限 000001)
|
||||
"""
|
||||
from django.core.paginator import Paginator
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from houtai.utils import verify_kefu_permission
|
||||
from yonghu.models import Xiugaijilu, UserMain
|
||||
from yonghu.xiugai_log import LEIXING_NAME
|
||||
|
||||
|
||||
def _fmt_dt(dt):
|
||||
if not dt:
|
||||
return ''
|
||||
return dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
def _fmt_dec(v):
|
||||
if v is None:
|
||||
return '0.00'
|
||||
return f'{v:.2f}'
|
||||
|
||||
|
||||
def serialize_xiugai_row(row: Xiugaijilu) -> dict:
|
||||
return {
|
||||
'id': row.id,
|
||||
'beixiugai_yonghuid': row.yonghuid or '',
|
||||
'xiugaizhe_zhanghao': row.xiugaiid or '',
|
||||
'leixing': row.leixing,
|
||||
'leixing_name': LEIXING_NAME.get(row.leixing, f'类型{row.leixing}'),
|
||||
'dashou_yue_qian': _fmt_dec(row.xiugaitijiaoq),
|
||||
'dashou_yue_hou': _fmt_dec(row.xiugaitijiao),
|
||||
'dashou_jifen_qian': int(row.yjifen or 0),
|
||||
'dashou_jifen_hou': int(row.jifen or 0),
|
||||
'dashou_yajin_qian': _fmt_dec(row.yyajin),
|
||||
'dashou_yajin_hou': _fmt_dec(row.yajin),
|
||||
'shangjia_yue_qian': _fmt_dec(row.shangjiayueq),
|
||||
'shangjia_yue_hou': _fmt_dec(row.shangjiayue),
|
||||
'guanshi_yue_qian': _fmt_dec(row.guanshiyueq),
|
||||
'guanshi_yue_hou': _fmt_dec(row.guanshiyue),
|
||||
'zuzhang_yue_qian': _fmt_dec(row.zuzhangyueq),
|
||||
'zuzhang_yue_hou': _fmt_dec(row.zuzhangyue),
|
||||
'huiyuants': int(row.huiyuants or 0),
|
||||
'huiyuan_id': row.huiyuan_id or '',
|
||||
'qitashuoming': row.qitashuoming or '',
|
||||
'create_time': _fmt_dt(row.create_time),
|
||||
}
|
||||
|
||||
|
||||
class GetCaozuoRizhiView(APIView):
|
||||
"""
|
||||
查询某后台账号的操作日志
|
||||
POST /houtai/hqczrz
|
||||
权限:000001
|
||||
参数:
|
||||
username: 当前登录客服账号
|
||||
phone: 要查看的操作人账号(对应 xiugaijilu.xiugaiid)
|
||||
page / pageSize
|
||||
yonghuid: 可选,按被操作用户筛选
|
||||
leixing: 可选,按用户类型筛选(2打手/3管事/4商家/5组长/9后台账号/0系统)
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def post(self, request):
|
||||
username = (request.data.get('username') or '').strip()
|
||||
if not username:
|
||||
return Response({'code': 400, 'msg': '缺少username'})
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, username)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '000001' not in permissions:
|
||||
return Response({'code': 403, 'msg': '您无权查看操作日志'})
|
||||
|
||||
phone = (request.data.get('phone') or '').strip()
|
||||
if not phone:
|
||||
return Response({'code': 400, 'msg': '缺少要查看的账号 phone'})
|
||||
|
||||
try:
|
||||
page = max(1, int(request.data.get('page', 1)))
|
||||
except (TypeError, ValueError):
|
||||
page = 1
|
||||
try:
|
||||
page_size = int(request.data.get('pageSize', request.data.get('pagesize', 20)))
|
||||
except (TypeError, ValueError):
|
||||
page_size = 20
|
||||
page_size = min(max(page_size, 1), 100)
|
||||
|
||||
qs = Xiugaijilu.objects.filter(xiugaiid=phone).order_by('-create_time', '-id')
|
||||
|
||||
yonghuid = (request.data.get('yonghuid') or '').strip()
|
||||
if yonghuid:
|
||||
qs = qs.filter(yonghuid=yonghuid)
|
||||
|
||||
leixing_raw = request.data.get('leixing')
|
||||
if leixing_raw is not None and str(leixing_raw).strip() != '':
|
||||
try:
|
||||
qs = qs.filter(leixing=int(leixing_raw))
|
||||
except (TypeError, ValueError):
|
||||
return Response({'code': 400, 'msg': 'leixing 无效'})
|
||||
|
||||
paginator = Paginator(qs, page_size)
|
||||
page_obj = paginator.get_page(page)
|
||||
data_list = [serialize_xiugai_row(row) for row in page_obj]
|
||||
|
||||
# 附带被操作用户头像(可选)
|
||||
yids = {d['beixiugai_yonghuid'] for d in data_list if d['beixiugai_yonghuid']}
|
||||
avatar_map = {}
|
||||
if yids:
|
||||
for um in UserMain.objects.filter(yonghuid__in=yids).only('yonghuid', 'avatar'):
|
||||
avatar_map[um.yonghuid] = um.avatar or ''
|
||||
for d in data_list:
|
||||
d['touxiang'] = avatar_map.get(d['beixiugai_yonghuid'], '')
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '获取成功',
|
||||
'data': {
|
||||
'list': data_list,
|
||||
'total': paginator.count,
|
||||
'page': page,
|
||||
'pageSize': page_size,
|
||||
'has_more': page_obj.has_next(),
|
||||
}
|
||||
})
|
||||
@@ -66,6 +66,22 @@ class DongjieUserConfigView(APIView):
|
||||
try:
|
||||
with transaction.atomic():
|
||||
data = save_user_freeze_settings(user_main, leixing, request.data)
|
||||
from yonghu.xiugai_log import (
|
||||
write_xiugai_log, FREEZE_TO_XIUGAI_LEIXING, FREEZE_LEIXING_NAME,
|
||||
)
|
||||
role_name = FREEZE_LEIXING_NAME.get(leixing, str(leixing))
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=FREEZE_TO_XIUGAI_LEIXING.get(leixing, 0),
|
||||
qitashuoming=(
|
||||
f'保存用户冻结配置[{role_name}]:'
|
||||
f'单独开关={data.get("dandu_dongjie_enabled")},'
|
||||
f'模式={data.get("dongjie_mode")},'
|
||||
f'比例={data.get("dongjie_bili")},'
|
||||
f'固定额={data.get("dongjie_guding_jine")}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '保存成功', 'data': data})
|
||||
except ValueError as e:
|
||||
return Response({'code': 400, 'msg': str(e)})
|
||||
@@ -81,6 +97,35 @@ class DongjieUserConfigView(APIView):
|
||||
user_main, leixing, jine,
|
||||
operator_id=username, beizhu=beizhu,
|
||||
)
|
||||
from yonghu.xiugai_log import (
|
||||
write_xiugai_log, FREEZE_TO_XIUGAI_LEIXING, FREEZE_LEIXING_NAME,
|
||||
)
|
||||
role_name = FREEZE_LEIXING_NAME.get(leixing, str(leixing))
|
||||
xiugai_leixing = FREEZE_TO_XIUGAI_LEIXING.get(leixing, 0)
|
||||
log_kwargs = {
|
||||
'yonghuid': yonghuid,
|
||||
'operator_phone': kefu.user.phone,
|
||||
'leixing': xiugai_leixing,
|
||||
'qitashuoming': (
|
||||
f'管理员解冻[{role_name}] {result["unfreeze_jine"]},'
|
||||
f'余额 {result["balance_before"]}→{result["balance_after"]},'
|
||||
f'冻结池 {result["dongjie_chi_before"]}→{result["dongjie_chi_after"]}'
|
||||
+ (f';备注:{beizhu}' if beizhu else '')
|
||||
),
|
||||
}
|
||||
if leixing == 1:
|
||||
log_kwargs['dashou_yue_before'] = result['balance_before']
|
||||
log_kwargs['dashou_yue_after'] = result['balance_after']
|
||||
elif leixing == 5:
|
||||
log_kwargs['yajin_before'] = result['balance_before']
|
||||
log_kwargs['yajin_after'] = result['balance_after']
|
||||
elif leixing == 2:
|
||||
log_kwargs['guanshi_yue_before'] = result['balance_before']
|
||||
log_kwargs['guanshi_yue_after'] = result['balance_after']
|
||||
elif leixing == 6:
|
||||
log_kwargs['shangjia_yue_before'] = result['balance_before']
|
||||
log_kwargs['shangjia_yue_after'] = result['balance_after']
|
||||
write_xiugai_log(**log_kwargs)
|
||||
info = get_user_freeze_info(user_main, leixing)
|
||||
info['balance'] = str(result['balance_after'])
|
||||
info['dongjie_chi'] = str(result['dongjie_chi_after'])
|
||||
|
||||
@@ -19,6 +19,7 @@ from .view import GetClubConfigView, GetCrossOrderListView, PartnerGetOrderDataV
|
||||
KhgglView, ShgxgsjView, ZxkfghdsView, KptxwztjbView
|
||||
from .dongjie_views import DongjieUserConfigView
|
||||
from .tixian_profit_views import TixianChouchengProfitView
|
||||
from .caozuo_rizhi_views import GetCaozuoRizhiView
|
||||
from .huashu_views import HuashuListAPIView, HuashuModifyAPIView
|
||||
from .xieyi_views import (
|
||||
XieyiListAPIView, XieyiModifyAPIView, XieyiImageUploadAPIView,
|
||||
@@ -56,6 +57,7 @@ urlpatterns = [
|
||||
|
||||
path('hqyhjsgl', GetAdminRolesView.as_view(), name='管理用户页面获取用户角色'),
|
||||
path('hqjsyhsj', GetAdminUserListView.as_view(), name='管理用户页面获取用户数据'),
|
||||
path('hqczrz', GetCaozuoRizhiView.as_view(), name='管理用户页面获取操作日志'),
|
||||
path('xghtyhsj', ModifyAdminUserView.as_view(), name='管理用户页面修改用户数据'),
|
||||
path('tjyhjs', AddAdminUserView.as_view(), name='管理用户页面添加用户'),
|
||||
path('kefuhqdslb', KefuGetDashouListView.as_view(), name='客服获取打手数据'),
|
||||
|
||||
234
houtai/view.py
234
houtai/view.py
@@ -4048,6 +4048,13 @@ class GetAdminUserListView(APIView):
|
||||
|
||||
# 构建返回数据
|
||||
data_list = []
|
||||
phones = [user.phone for user in page_obj]
|
||||
log_counts = {
|
||||
row['xiugaiid']: row['c']
|
||||
for row in Xiugaijilu.objects.filter(xiugaiid__in=phones)
|
||||
.values('xiugaiid')
|
||||
.annotate(c=Count('id'))
|
||||
}
|
||||
for user in page_obj:
|
||||
# 获取用户的所有角色
|
||||
user_roles = UserRole.objects.filter(account_id=user.phone).select_related('role')
|
||||
@@ -4057,6 +4064,7 @@ class GetAdminUserListView(APIView):
|
||||
'nicheng': user.kefu_profile.nicheng,
|
||||
'roles': roles_data,
|
||||
'status': user.kefu_profile.zhuangtai,
|
||||
'jilushuliang': int(log_counts.get(user.phone, 0)),
|
||||
'create_time': user.create_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'update_time': user.update_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
})
|
||||
@@ -4109,32 +4117,60 @@ class ModifyAdminUserView(APIView):
|
||||
status = request.data.get('status')
|
||||
password = request.data.get('password')
|
||||
erjimima = request.data.get('erjimima')
|
||||
if nicheng is not None:
|
||||
old_nicheng = target_kefu.nicheng
|
||||
old_status = target_kefu.zhuangtai
|
||||
changed = []
|
||||
if nicheng is not None and nicheng != old_nicheng:
|
||||
target_kefu.nicheng = nicheng
|
||||
changed.append(f'昵称 {old_nicheng}→{nicheng}')
|
||||
if status is not None:
|
||||
target_kefu.zhuangtai = int(status)
|
||||
new_status = int(status)
|
||||
if new_status != old_status:
|
||||
target_kefu.zhuangtai = new_status
|
||||
changed.append(f'状态 {old_status}→{new_status}({"正常" if new_status == 1 else "禁用"})')
|
||||
if password:
|
||||
if len(password) < 6:
|
||||
return Response({'code': 400, 'msg': '密码至少6位'})
|
||||
target_user.password = password
|
||||
changed.append('修改登录密码')
|
||||
if erjimima:
|
||||
if len(erjimima) < 6:
|
||||
return Response({'code': 400, 'msg': '二级密码至少6位'})
|
||||
target_kefu.erjimima = erjimima # 假设二级密码也需要加密
|
||||
changed.append('修改二级密码')
|
||||
target_user.save()
|
||||
target_kefu.save()
|
||||
if changed:
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_KEFU
|
||||
write_xiugai_log(
|
||||
yonghuid=target_user.yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_KEFU,
|
||||
qitashuoming=f'后台账号[{target_phone}]:' + ';'.join(changed),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
elif action == 'add_user_roles':
|
||||
role_codes = request.data.get('role_codes', [])
|
||||
if not role_codes:
|
||||
return Response({'code': 400, 'msg': '请选择角色'})
|
||||
added = []
|
||||
for rc in role_codes:
|
||||
try:
|
||||
role = Role.objects.get(role_code=rc)
|
||||
except Role.DoesNotExist:
|
||||
continue
|
||||
UserRole.objects.get_or_create(account_id=target_phone, role=role)
|
||||
_, created = UserRole.objects.get_or_create(account_id=target_phone, role=role)
|
||||
if created:
|
||||
added.append(f'{role.role_name}({rc})')
|
||||
if added:
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_KEFU
|
||||
write_xiugai_log(
|
||||
yonghuid=target_user.yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_KEFU,
|
||||
qitashuoming=f'后台账号[{target_phone}]添加角色:{",".join(added)}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '角色添加成功'})
|
||||
|
||||
elif action == 'remove_user_role':
|
||||
@@ -4145,7 +4181,15 @@ class ModifyAdminUserView(APIView):
|
||||
role = Role.objects.get(role_code=role_code)
|
||||
except Role.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '角色不存在'})
|
||||
UserRole.objects.filter(account_id=target_phone, role=role).delete()
|
||||
deleted, _ = UserRole.objects.filter(account_id=target_phone, role=role).delete()
|
||||
if deleted:
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_KEFU
|
||||
write_xiugai_log(
|
||||
yonghuid=target_user.yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_KEFU,
|
||||
qitashuoming=f'后台账号[{target_phone}]移除角色:{role.role_name}({role_code})',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '角色移除成功'})
|
||||
|
||||
else:
|
||||
@@ -4178,6 +4222,9 @@ class AddAdminUserView(APIView):
|
||||
|
||||
if not all([phone, password, erjimima, nicheng]):
|
||||
return Response({'code': 400, 'msg': '请填写完整信息'})
|
||||
# UserMain.phone / UserRole.account_id 均为 max_length=11
|
||||
if len(phone) > 11:
|
||||
return Response({'code': 400, 'msg': '账号最长11位,请使用手机号'})
|
||||
if len(password) < 6 or len(erjimima) < 6:
|
||||
return Response({'code': 400, 'msg': '密码和二级密码至少6位'})
|
||||
|
||||
@@ -4222,6 +4269,14 @@ class AddAdminUserView(APIView):
|
||||
except Role.DoesNotExist:
|
||||
pass
|
||||
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_KEFU
|
||||
write_xiugai_log(
|
||||
yonghuid=user_main.yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_KEFU,
|
||||
qitashuoming=f'新增后台账号[{phone}]昵称={nicheng},角色={role_codes}',
|
||||
)
|
||||
|
||||
return Response({'code': 0, 'msg': '添加成功'})
|
||||
|
||||
|
||||
@@ -4706,6 +4761,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
xiugaitijiao=after,
|
||||
xiugaitijiaoq=before['yue'],
|
||||
qitashuoming=f'打手减余额 {amount},{before["yue"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减余额成功', 'data': {'new_yue': str(after)}})
|
||||
|
||||
@@ -4722,6 +4778,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
xiugaitijiao=after,
|
||||
xiugaitijiaoq=before['yue'],
|
||||
qitashuoming=f'打手加余额 {amount},{before["yue"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加余额成功', 'data': {'new_yue': str(after)}})
|
||||
|
||||
@@ -4741,6 +4798,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
yajin=after,
|
||||
yyajin=before['yajin'],
|
||||
qitashuoming=f'打手减押金 {amount},{before["yajin"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减押金成功', 'data': {'new_yajin': str(after)}})
|
||||
|
||||
@@ -4757,6 +4815,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
yajin=after,
|
||||
yyajin=before['yajin'],
|
||||
qitashuoming=f'打手加押金 {amount},{before["yajin"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加押金成功', 'data': {'new_yajin': str(after)}})
|
||||
|
||||
@@ -4776,6 +4835,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
jifen=after,
|
||||
yjifen=before['jifen'],
|
||||
qitashuoming=f'打手减积分 {jifen},{before["jifen"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减积分成功', 'data': {'new_jifen': after}})
|
||||
|
||||
@@ -4792,6 +4852,7 @@ class KefuUpdateDashouView(APIView):
|
||||
leixing=2,
|
||||
jifen=after,
|
||||
yjifen=before['jifen'],
|
||||
qitashuoming=f'打手加积分 {jifen},{before["jifen"]} → {after}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加积分成功', 'data': {'new_jifen': after}})
|
||||
|
||||
@@ -4808,7 +4869,7 @@ class KefuUpdateDashouView(APIView):
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.phone,
|
||||
leixing=2,
|
||||
qitashuoming=f'修改账号状态为{new_status}',
|
||||
qitashuoming=f'打手账号{"解封" if new_status == 1 else "封禁"},状态→{new_status}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改账号状态成功', 'data': {'new_zhanghaozhuangtai': new_status}})
|
||||
|
||||
@@ -5186,11 +5247,21 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '金额需在0.01~1000000之间'})
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '金额格式错误'})
|
||||
new_yue = shangjia.yue + amount
|
||||
old_yue = shangjia.yue
|
||||
new_yue = old_yue + amount
|
||||
if new_yue > 999999999.99:
|
||||
return Response({'code': 400, 'msg': '增加后余额超出上限'})
|
||||
shangjia.yue = new_yue
|
||||
shangjia.save(update_fields=['yue'])
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SHANGJIA
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SHANGJIA,
|
||||
shangjia_yue_before=old_yue,
|
||||
shangjia_yue_after=new_yue,
|
||||
qitashuoming=f'商家加余额 {amount},{old_yue} → {new_yue}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '余额增加成功', 'data': {'new_balance': str(shangjia.yue)}})
|
||||
|
||||
# 减少余额
|
||||
@@ -5202,26 +5273,53 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '金额需在0.01~1000000之间'})
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '金额格式错误'})
|
||||
if shangjia.yue < amount:
|
||||
old_yue = shangjia.yue
|
||||
if old_yue < amount:
|
||||
return Response({'code': 400, 'msg': '余额不足'})
|
||||
shangjia.yue = shangjia.yue - amount
|
||||
new_yue = old_yue - amount
|
||||
shangjia.yue = new_yue
|
||||
shangjia.save(update_fields=['yue'])
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SHANGJIA
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SHANGJIA,
|
||||
shangjia_yue_before=old_yue,
|
||||
shangjia_yue_after=new_yue,
|
||||
qitashuoming=f'商家减余额 {amount},{old_yue} → {new_yue}',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '余额减少成功', 'data': {'new_balance': str(shangjia.yue)}})
|
||||
|
||||
# 封禁
|
||||
if action == 'ban':
|
||||
if shangjia.zhuangtai == 2:
|
||||
return Response({'code': 400, 'msg': '商家已是封禁状态'})
|
||||
old_zt = shangjia.zhuangtai
|
||||
shangjia.zhuangtai = 2
|
||||
shangjia.save(update_fields=['zhuangtai'])
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SHANGJIA
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SHANGJIA,
|
||||
qitashuoming=f'商家封禁,状态 {old_zt} → 2',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '商家已封禁', 'data': {'zhuangtai': 2}})
|
||||
|
||||
# 解封
|
||||
if action == 'unban':
|
||||
if shangjia.zhuangtai == 1:
|
||||
return Response({'code': 400, 'msg': '商家已是正常状态'})
|
||||
old_zt = shangjia.zhuangtai
|
||||
shangjia.zhuangtai = 1
|
||||
shangjia.save(update_fields=['zhuangtai'])
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SHANGJIA
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SHANGJIA,
|
||||
qitashuoming=f'商家解封,状态 {old_zt} → 1',
|
||||
)
|
||||
return Response({'code': 0, 'msg': '商家已解封', 'data': {'zhuangtai': 1}})
|
||||
|
||||
|
||||
@@ -6506,6 +6604,11 @@ class UpdateGuanliView(APIView):
|
||||
guanshi = user.guanshi_profile
|
||||
boss = user.boss_profile if hasattr(user, 'boss_profile') else None
|
||||
|
||||
old_yue = guanshi.yue
|
||||
old_zhuangtai = guanshi.zhuangtai
|
||||
old_kaioi = guanshi.kaioi_ewai_xiane
|
||||
old_ewai = guanshi.ewai_xiane
|
||||
|
||||
# ---------- 1. 基础信息修改(需要4400a)----------
|
||||
nickname = request.data.get('nickname')
|
||||
dianhua = request.data.get('dianhua')
|
||||
@@ -6550,7 +6653,6 @@ class UpdateGuanliView(APIView):
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '余额格式错误'})
|
||||
|
||||
old_yue = guanshi.yue
|
||||
if new_yue > old_yue:
|
||||
if '4400c' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限增加余额(需要4400c)'})
|
||||
@@ -6580,10 +6682,12 @@ class UpdateGuanliView(APIView):
|
||||
perm_amount = request.data.get('permanent_amount')
|
||||
custom_first = request.data.get('custom_first_dividend')
|
||||
extra_map = request.data.get('extra_dividend_map')
|
||||
fenhong_changed = False
|
||||
|
||||
if any(v is not None for v in [perm_enabled, perm_amount, custom_first, extra_map]):
|
||||
if '4400f' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限修改分红策略(需要4400f)'})
|
||||
fenhong_changed = True
|
||||
|
||||
# 4.1 永久分红
|
||||
if perm_enabled is not None:
|
||||
@@ -6663,6 +6767,48 @@ class UpdateGuanliView(APIView):
|
||||
if (record.cishu, record.huiyuan) not in keep_set:
|
||||
record.delete()
|
||||
|
||||
# ---------- 敏感操作写日志 ----------
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_GUANSHI
|
||||
op_phone = kefu.user.phone
|
||||
if guanshi.yue != old_yue:
|
||||
delta = guanshi.yue - old_yue
|
||||
act = '加余额' if delta > 0 else '减余额'
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_GUANSHI,
|
||||
guanshi_yue_before=old_yue,
|
||||
guanshi_yue_after=guanshi.yue,
|
||||
qitashuoming=f'管事{act} {abs(delta)},{old_yue} → {guanshi.yue}',
|
||||
)
|
||||
if guanshi.zhuangtai != old_zhuangtai:
|
||||
zt_txt = '解封' if guanshi.zhuangtai == 1 else '封禁'
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_GUANSHI,
|
||||
qitashuoming=f'管事{zt_txt},状态 {old_zhuangtai} → {guanshi.zhuangtai}',
|
||||
)
|
||||
if (kaioi_ewai is not None or ewai_val is not None) and (
|
||||
guanshi.kaioi_ewai_xiane != old_kaioi or guanshi.ewai_xiane != old_ewai
|
||||
):
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'管事提现限额变更:开关 {old_kaioi}→{guanshi.kaioi_ewai_xiane},'
|
||||
f'额外限额 {old_ewai}→{guanshi.ewai_xiane}'
|
||||
),
|
||||
)
|
||||
if fenhong_changed:
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_GUANSHI,
|
||||
qitashuoming='管事分红策略变更(永久/首次定制/额外次数)',
|
||||
)
|
||||
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
|
||||
@@ -6900,6 +7046,25 @@ class UpdateWithdrawSettingsView(APIView):
|
||||
bool(request.data.get('dongjie_quanju_enabled', False)),
|
||||
request.data.get('dongjie_roles', []),
|
||||
)
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SYSTEM
|
||||
write_xiugai_log(
|
||||
yonghuid='0000000',
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SYSTEM,
|
||||
qitashuoming=(
|
||||
f'修改全局冻结配置:开关={request.data.get("dongjie_quanju_enabled")},'
|
||||
f'角色配置={request.data.get("dongjie_roles")}'
|
||||
),
|
||||
)
|
||||
|
||||
if withdraw_mode is not None:
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_SYSTEM
|
||||
write_xiugai_log(
|
||||
yonghuid='0000000',
|
||||
operator_phone=kefu.user.phone,
|
||||
leixing=LEIXING_SYSTEM,
|
||||
qitashuoming=f'修改提现模式为 {withdraw_mode}(1自动/2手动)',
|
||||
)
|
||||
|
||||
# 注意:TixianRiTongji 表由提现流程自动更新,此处不直接修改
|
||||
return Response({'code': 0, 'msg': '设置修改成功'})
|
||||
@@ -7215,6 +7380,9 @@ class UpdateZuzhangView(APIView):
|
||||
|
||||
# 获取原始数据(用于对比金额变化)
|
||||
old_ketixian_jine = zuzhang.ketixian_jine
|
||||
old_zhuangtai = zuzhang.zhuangtai
|
||||
old_kaioi = zuzhang.kaioi_ewai_tixian
|
||||
old_ewai = zuzhang.ewai_tixian_xiane
|
||||
|
||||
# 开始事务
|
||||
with transaction.atomic():
|
||||
@@ -7284,10 +7452,12 @@ class UpdateZuzhangView(APIView):
|
||||
perm_amount = request.data.get('permanent_amount')
|
||||
custom_first = request.data.get('custom_first_dividend')
|
||||
extra_map = request.data.get('extra_dividend_map')
|
||||
fenhong_changed = False
|
||||
|
||||
if any(v is not None for v in [perm_enabled, perm_amount, custom_first, extra_map]):
|
||||
if '6600e' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限修改分红策略(需要6600e)'})
|
||||
fenhong_changed = True
|
||||
|
||||
# 4.1 永久分红(额外分红开关和金额)
|
||||
if perm_enabled is not None:
|
||||
@@ -7363,7 +7533,51 @@ class UpdateZuzhangView(APIView):
|
||||
if (record.cishu, record.huiyuan) not in keep_set:
|
||||
record.delete()
|
||||
|
||||
# 保存组长其他可能修改的字段(例如电话、微信没有,忽略)
|
||||
# 保存状态字段
|
||||
if zhuangtai is not None:
|
||||
zuzhang.save(update_fields=['zhuangtai'])
|
||||
|
||||
# ---------- 敏感操作写日志 ----------
|
||||
from yonghu.xiugai_log import write_xiugai_log, LEIXING_ZUZHANG
|
||||
op_phone = kefu.user.phone
|
||||
if zuzhang.ketixian_jine != old_ketixian_jine:
|
||||
delta = zuzhang.ketixian_jine - old_ketixian_jine
|
||||
act = '加可提现' if delta > 0 else '减可提现'
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_ZUZHANG,
|
||||
zuzhang_yue_before=old_ketixian_jine,
|
||||
zuzhang_yue_after=zuzhang.ketixian_jine,
|
||||
qitashuoming=f'组长{act} {abs(delta)},{old_ketixian_jine} → {zuzhang.ketixian_jine}',
|
||||
)
|
||||
if zuzhang.zhuangtai != old_zhuangtai:
|
||||
zt_txt = '解封' if zuzhang.zhuangtai == 1 else '封禁'
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_ZUZHANG,
|
||||
qitashuoming=f'组长{zt_txt},状态 {old_zhuangtai} → {zuzhang.zhuangtai}',
|
||||
)
|
||||
if (kaioi_ewai is not None or ewai_val is not None) and (
|
||||
zuzhang.kaioi_ewai_tixian != old_kaioi or zuzhang.ewai_tixian_xiane != old_ewai
|
||||
):
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_ZUZHANG,
|
||||
qitashuoming=(
|
||||
f'组长提现限额变更:开关 {old_kaioi}→{zuzhang.kaioi_ewai_tixian},'
|
||||
f'额外限额 {old_ewai}→{zuzhang.ewai_tixian_xiane}'
|
||||
),
|
||||
)
|
||||
if fenhong_changed:
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
operator_phone=op_phone,
|
||||
leixing=LEIXING_ZUZHANG,
|
||||
qitashuoming='组长分红策略变更(永久/首次定制/额外次数)',
|
||||
)
|
||||
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user