feat: 更换邀请人、操作日志与组长列表搜索修复
复用 xiugaijilu 为后台关键改动补全详细日志,新增更换打手/管事邀请人接口与操作日志页面,并修复组长列表 BossProfile 关联名导致的搜索 500。
This commit is contained in:
529
backend/view.py
529
backend/view.py
@@ -50,6 +50,12 @@ from .utils import (
|
||||
check_fadan_permission,
|
||||
pick_order_id,
|
||||
pick_penalty_create_params,
|
||||
write_xiugai_log,
|
||||
XIUGAI_LEIXING_DASHOU,
|
||||
XIUGAI_LEIXING_GUANSHI,
|
||||
XIUGAI_LEIXING_SHANGJIA,
|
||||
XIUGAI_LEIXING_ZUZHANG,
|
||||
XIUGAI_LEIXING_LABEL,
|
||||
)
|
||||
|
||||
# models 集中导入
|
||||
@@ -1004,12 +1010,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.yue -= amount
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.yue
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
xiugaitijiao=after,
|
||||
xiugaitijiaoq=before['yue'],
|
||||
qitashuoming=(
|
||||
f'【后台】减少打手可提现余额:{before["yue"]}元 → {after}元,'
|
||||
f'减少{amount}元,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减余额成功', 'data': {'new_yue': str(after)}})
|
||||
|
||||
@@ -1020,12 +1030,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.yue += amount
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.yue
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
xiugaitijiao=after,
|
||||
xiugaitijiaoq=before['yue'],
|
||||
qitashuoming=(
|
||||
f'【后台】增加打手可提现余额:{before["yue"]}元 → {after}元,'
|
||||
f'增加{amount}元,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加余额成功', 'data': {'new_yue': str(after)}})
|
||||
|
||||
@@ -1039,12 +1053,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.yajin -= amount
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.yajin
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
yajin=after,
|
||||
yyajin=before['yajin'],
|
||||
qitashuoming=(
|
||||
f'【后台】减少打手押金:{before["yajin"]}元 → {after}元,'
|
||||
f'减少{amount}元,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减押金成功', 'data': {'new_yajin': str(after)}})
|
||||
|
||||
@@ -1055,12 +1073,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.yajin += amount
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.yajin
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
yajin=after,
|
||||
yyajin=before['yajin'],
|
||||
qitashuoming=(
|
||||
f'【后台】增加打手押金:{before["yajin"]}元 → {after}元,'
|
||||
f'增加{amount}元,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加押金成功', 'data': {'new_yajin': str(after)}})
|
||||
|
||||
@@ -1074,12 +1096,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.jifen -= jifen
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.jifen
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
jifen=after,
|
||||
yjifen=before['jifen'],
|
||||
qitashuoming=(
|
||||
f'【后台】减少打手积分:{before["jifen"]} → {after},'
|
||||
f'减少{jifen}分,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减积分成功', 'data': {'new_jifen': after}})
|
||||
|
||||
@@ -1090,12 +1116,16 @@ class KefuUpdateDashouView(APIView):
|
||||
dashou_profile.jifen += jifen
|
||||
dashou_profile.save()
|
||||
after = dashou_profile.jifen
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
jifen=after,
|
||||
yjifen=before['jifen'],
|
||||
qitashuoming=(
|
||||
f'【后台】增加打手积分:{before["jifen"]} → {after},'
|
||||
f'增加{jifen}分,打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加积分成功', 'data': {'new_jifen': after}})
|
||||
|
||||
@@ -1108,11 +1138,16 @@ class KefuUpdateDashouView(APIView):
|
||||
return Response({'code': 400, 'msg': '状态值无效(0=封禁,1=正常)'})
|
||||
dashou_profile.zhanghaozhuangtai = new_status
|
||||
dashou_profile.save()
|
||||
Xiugaijilu.query.create(
|
||||
status_label = '正常' if new_status == 1 else '封禁'
|
||||
old_label = '正常' if before['zhanghaozhuangtai'] == 1 else '封禁'
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
qitashuoming=f'修改账号状态为{new_status}',
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
qitashuoming=(
|
||||
f'【后台】修改打手账号状态:{old_label} → {status_label},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改账号状态成功', 'data': {'new_zhanghaozhuangtai': new_status}})
|
||||
|
||||
@@ -1124,11 +1159,16 @@ class KefuUpdateDashouView(APIView):
|
||||
return Response({'code': 400, 'msg': '状态值无效(0=离线,1=在线)'})
|
||||
dashou_profile.zaixianzhuangtai = new_status
|
||||
dashou_profile.save()
|
||||
Xiugaijilu.query.create(
|
||||
status_label = '在线' if new_status == 1 else '离线'
|
||||
old_label = '在线' if before['zaixianzhuangtai'] == 1 else '离线'
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
qitashuoming=f'修改在线状态为{new_status}',
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
qitashuoming=(
|
||||
f'【后台】修改打手在线状态:{old_label} → {status_label},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改在线状态成功', 'data': {'new_zaixianzhuangtai': new_status}})
|
||||
|
||||
@@ -1140,11 +1180,16 @@ class KefuUpdateDashouView(APIView):
|
||||
return Response({'code': 400, 'msg': '状态值无效(0=忙碌,1=空闲)'})
|
||||
dashou_profile.zhuangtai = new_status
|
||||
dashou_profile.save()
|
||||
Xiugaijilu.query.create(
|
||||
status_label = '空闲' if new_status == 1 else '忙碌'
|
||||
old_label = '空闲' if before['zhuangtai'] == 1 else '忙碌'
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
qitashuoming=f'修改接单状态为{new_status}',
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
qitashuoming=(
|
||||
f'【后台】修改打手接单状态:{old_label} → {status_label},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改接单状态成功', 'data': {'new_zhuangtai': new_status}})
|
||||
|
||||
@@ -1173,13 +1218,17 @@ class KefuUpdateDashouView(APIView):
|
||||
record.daoqi_time = new_daoqi
|
||||
record.huiyuan_zhuangtai = 1
|
||||
record.save()
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
huiyuants=days,
|
||||
huiyuan_id=huiyuan_id,
|
||||
qitashuoming=f'加会员 {huiyuan_id},增加{days}天',
|
||||
qitashuoming=(
|
||||
f'【后台】给打手添加会员:会员ID={huiyuan_id}({huiyuan.jieshao}),'
|
||||
f'增加{days}天,到期时间={record.daoqi_time.strftime("%Y-%m-%d %H:%M:%S")},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '加会员成功', 'data': {'new_daoqi': record.daoqi_time.strftime('%Y-%m-%d %H:%M:%S')}})
|
||||
|
||||
@@ -1193,12 +1242,15 @@ class KefuUpdateDashouView(APIView):
|
||||
except Huiyuangoumai.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '该打手未购买此会员'})
|
||||
record.delete()
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
huiyuan_id=huiyuan_id,
|
||||
qitashuoming=f'移除会员 {huiyuan_id}',
|
||||
qitashuoming=(
|
||||
f'【后台】移除打手会员:会员ID={huiyuan_id},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '减会员成功'})
|
||||
|
||||
@@ -1212,11 +1264,14 @@ class KefuUpdateDashouView(APIView):
|
||||
# 可限制合法值,这里只记录日志
|
||||
dashou_profile.chenghao = new_chenghao
|
||||
dashou_profile.save()
|
||||
Xiugaijilu.query.create(
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=2,
|
||||
qitashuoming=f'修改称号:{before["chenghao"] or "无"} → {new_chenghao}',
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
qitashuoming=(
|
||||
f'【后台】修改打手称号:{before["chenghao"] or "无"} → {new_chenghao},'
|
||||
f'打手ID={dashou_id},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '修改称号成功', 'data': {'new_chenghao': new_chenghao}})
|
||||
|
||||
@@ -1490,11 +1545,23 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '金额需在0.01~1000000之间'})
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '金额格式错误'})
|
||||
old_yue = shangjia.yue
|
||||
new_yue = shangjia.yue + amount
|
||||
if new_yue > 999999999.99:
|
||||
return Response({'code': 400, 'msg': '增加后余额超出上限'})
|
||||
shangjia.yue = new_yue
|
||||
shangjia.save(update_fields=['yue'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=XIUGAI_LEIXING_SHANGJIA,
|
||||
shangjiayue=new_yue,
|
||||
shangjiayueq=old_yue,
|
||||
qitashuoming=(
|
||||
f'【后台】增加商家余额:{old_yue}元 → {new_yue}元,增加{amount}元,'
|
||||
f'商家ID={yonghuid},昵称={shangjia.nicheng},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '余额增加成功', 'data': {'new_balance': str(shangjia.yue)}})
|
||||
|
||||
# 减少余额
|
||||
@@ -1508,8 +1575,20 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '金额格式错误'})
|
||||
if shangjia.yue < amount:
|
||||
return Response({'code': 400, 'msg': '余额不足'})
|
||||
old_yue = shangjia.yue
|
||||
shangjia.yue = shangjia.yue - amount
|
||||
shangjia.save(update_fields=['yue'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=XIUGAI_LEIXING_SHANGJIA,
|
||||
shangjiayue=shangjia.yue,
|
||||
shangjiayueq=old_yue,
|
||||
qitashuoming=(
|
||||
f'【后台】减少商家余额:{old_yue}元 → {shangjia.yue}元,减少{amount}元,'
|
||||
f'商家ID={yonghuid},昵称={shangjia.nicheng},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '余额减少成功', 'data': {'new_balance': str(shangjia.yue)}})
|
||||
|
||||
# 封禁
|
||||
@@ -1518,6 +1597,15 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '商家已是封禁状态'})
|
||||
shangjia.zhuangtai = 2
|
||||
shangjia.save(update_fields=['zhuangtai'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=XIUGAI_LEIXING_SHANGJIA,
|
||||
qitashuoming=(
|
||||
f'【后台】封禁商家账号:正常 → 禁用,'
|
||||
f'商家ID={yonghuid},昵称={shangjia.nicheng},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '商家已封禁', 'data': {'zhuangtai': 2}})
|
||||
|
||||
# 解封
|
||||
@@ -1526,6 +1614,15 @@ class KefuUpdateShangjiaView(APIView):
|
||||
return Response({'code': 400, 'msg': '商家已是正常状态'})
|
||||
shangjia.zhuangtai = 1
|
||||
shangjia.save(update_fields=['zhuangtai'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=XIUGAI_LEIXING_SHANGJIA,
|
||||
qitashuoming=(
|
||||
f'【后台】解封商家账号:禁用 → 正常,'
|
||||
f'商家ID={yonghuid},昵称={shangjia.nicheng},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '商家已解封', 'data': {'zhuangtai': 1}})
|
||||
|
||||
|
||||
@@ -3059,6 +3156,16 @@ class PromoteGuanshiToZuzhangView(APIView):
|
||||
except IntegrityError:
|
||||
return Response({'code': 400, 'msg': '升级失败,请稍后重试'})
|
||||
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=kefu.user.Phone,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'【后台】管事升级组长:用户ID={yonghuid},'
|
||||
f'生成组长邀请码={zuzhang.yaoqingma},操作人={kefu.user.Phone}'
|
||||
),
|
||||
)
|
||||
|
||||
logger.info(f"管事升级组长成功: yonghuid={yonghuid}, yaoqingma={zuzhang.yaoqingma}")
|
||||
return Response({
|
||||
'code': 0,
|
||||
@@ -3119,6 +3226,7 @@ class UpdateGuanliView(APIView):
|
||||
user = User.objects.select_for_update().get(UserUID=yonghuid)
|
||||
guanshi = user.GuanshiProfile
|
||||
boss = user.BossProfile if hasattr(user, 'BossProfile') else None
|
||||
operator = kefu.user.Phone
|
||||
|
||||
# ---------- 1. 基础信息修改(需要4400a)----------
|
||||
nickname = request.data.get('nickname')
|
||||
@@ -3130,6 +3238,11 @@ class UpdateGuanliView(APIView):
|
||||
if any(v is not None for v in [nickname, dianhua, wechat, zhuangtai, avatar]):
|
||||
if '4400a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限修改管事基础信息(需要4400a)'})
|
||||
base_changes = []
|
||||
old_nickname = boss.nickname if boss else ''
|
||||
old_dianhua = guanshi.dianhua
|
||||
old_wechat = guanshi.wechat
|
||||
old_zhuangtai = guanshi.zhuangtai
|
||||
# 处理昵称(在老板扩展表中)
|
||||
if nickname is not None:
|
||||
if not boss:
|
||||
@@ -3137,22 +3250,42 @@ class UpdateGuanliView(APIView):
|
||||
else:
|
||||
boss.nickname = nickname
|
||||
boss.save()
|
||||
if str(nickname) != str(old_nickname):
|
||||
base_changes.append(f'昵称:{old_nickname or "无"}→{nickname}')
|
||||
# 处理其他字段
|
||||
if dianhua is not None:
|
||||
guanshi.dianhua = dianhua
|
||||
if str(dianhua) != str(old_dianhua):
|
||||
base_changes.append(f'电话:{old_dianhua or "无"}→{dianhua}')
|
||||
if wechat is not None:
|
||||
guanshi.wechat = wechat
|
||||
if str(wechat) != str(old_wechat):
|
||||
base_changes.append(f'微信:{old_wechat or "无"}→{wechat}')
|
||||
if zhuangtai is not None:
|
||||
try:
|
||||
zt = int(zhuangtai)
|
||||
if zt in (0, 1):
|
||||
guanshi.zhuangtai = zt
|
||||
if zt != old_zhuangtai:
|
||||
zt_map = {0: '禁用', 1: '正常'}
|
||||
base_changes.append(f'状态:{zt_map.get(old_zhuangtai, old_zhuangtai)}→{zt_map.get(zt, zt)}')
|
||||
except:
|
||||
pass
|
||||
if avatar is not None:
|
||||
user.Avatar = avatar
|
||||
user.save()
|
||||
base_changes.append('更新了头像')
|
||||
guanshi.save()
|
||||
if base_changes:
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'【后台】修改管事基础信息:{";".join(base_changes)},'
|
||||
f'管事ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# ---------- 2. 余额修改(加:4400c;减:4400b)----------
|
||||
new_yue = request.data.get('yue')
|
||||
@@ -3168,11 +3301,27 @@ class UpdateGuanliView(APIView):
|
||||
if new_yue > old_yue:
|
||||
if '4400c' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限增加余额(需要4400c)'})
|
||||
action_desc = f'增加{new_yue - old_yue}元'
|
||||
elif new_yue < old_yue:
|
||||
if '4400b' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限减少余额(需要4400b)'})
|
||||
guanshi.yue = new_yue
|
||||
guanshi.save()
|
||||
action_desc = f'减少{old_yue - new_yue}元'
|
||||
else:
|
||||
action_desc = '无变动'
|
||||
if new_yue != old_yue:
|
||||
guanshi.yue = new_yue
|
||||
guanshi.save()
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
guanshiyue=new_yue,
|
||||
guanshiyueq=old_yue,
|
||||
qitashuoming=(
|
||||
f'【后台】修改管事可提现余额:{old_yue}元 → {new_yue}元({action_desc}),'
|
||||
f'管事ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# ---------- 3. 提现限额修改(需要4400e)----------
|
||||
kaioi_ewai = request.data.get('kaioi_ewai_xiane')
|
||||
@@ -3180,14 +3329,31 @@ class UpdateGuanliView(APIView):
|
||||
if kaioi_ewai is not None or ewai_val is not None:
|
||||
if '4400e' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限修改提现限额(需要4400e)'})
|
||||
limit_changes = []
|
||||
old_kaioi = guanshi.kaioi_ewai_xiane
|
||||
old_ewai = guanshi.ewai_xiane
|
||||
if kaioi_ewai is not None:
|
||||
guanshi.kaioi_ewai_xiane = bool(kaioi_ewai)
|
||||
if bool(kaioi_ewai) != old_kaioi:
|
||||
limit_changes.append(f'额外限额开关:{"开" if old_kaioi else "关"}→{"开" if kaioi_ewai else "关"}')
|
||||
if ewai_val is not None:
|
||||
try:
|
||||
guanshi.ewai_xiane = Decimal(str(ewai_val))
|
||||
if guanshi.ewai_xiane != old_ewai:
|
||||
limit_changes.append(f'额外限额金额:{old_ewai}→{guanshi.ewai_xiane}')
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '额外限额金额格式错误'})
|
||||
guanshi.save()
|
||||
if limit_changes:
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'【后台】修改管事提现限额:{";".join(limit_changes)},'
|
||||
f'管事ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# ---------- 4. 分红相关修改(需要4400f)----------
|
||||
perm_enabled = request.data.get('permanent_enabled')
|
||||
@@ -3277,6 +3443,25 @@ class UpdateGuanliView(APIView):
|
||||
if (record.cishu, record.huiyuan) not in keep_set:
|
||||
record.delete()
|
||||
|
||||
dividend_parts = []
|
||||
if perm_enabled is not None:
|
||||
dividend_parts.append(f'永久分红开关→{"开" if perm_enabled else "关"}')
|
||||
if perm_amount is not None:
|
||||
dividend_parts.append(f'永久分红金额→{perm_amount}')
|
||||
if custom_first is not None:
|
||||
dividend_parts.append(f'更新首次定制分红({len(custom_first)}项)')
|
||||
if extra_map is not None:
|
||||
dividend_parts.append(f'更新额外次数分红({len(extra_map)}组)')
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'【后台】修改管事分红策略:{";".join(dividend_parts) or "配置已更新"},'
|
||||
f'管事ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
|
||||
@@ -3559,7 +3744,7 @@ class GetZuzhangListView(APIView):
|
||||
if keyword:
|
||||
queryset = queryset.filter(
|
||||
Q(user__UserUID__icontains=keyword) |
|
||||
Q(user__boss_profile__nickname__icontains=keyword)
|
||||
Q(user__BossProfile__nickname__icontains=keyword)
|
||||
)
|
||||
|
||||
if status is not None and status != '':
|
||||
@@ -3812,12 +3997,16 @@ class UpdateZuzhangView(APIView):
|
||||
|
||||
# 开始事务
|
||||
with transaction.atomic():
|
||||
operator = kefu.user.Phone
|
||||
old_nickname = boss.nickname if boss else ''
|
||||
old_zhuangtai = zuzhang.zhuangtai
|
||||
# ---------- 1. 基础信息修改(需要6600c?按需求,基础信息修改通常用6600c,但为了安全,暂不校验,如有需要可加)----------
|
||||
nickname = request.data.get('nickname', '').strip()
|
||||
avatar = request.data.get('avatar', '').strip()
|
||||
dianhua = request.data.get('dianhua', '').strip()
|
||||
wechat = request.data.get('wechat', '').strip()
|
||||
zhuangtai = request.data.get('zhuangtai')
|
||||
base_changes = []
|
||||
# 状态修改需要6600c
|
||||
if zhuangtai is not None:
|
||||
if '6600c' not in permissions:
|
||||
@@ -3826,6 +4015,9 @@ class UpdateZuzhangView(APIView):
|
||||
zt = int(zhuangtai)
|
||||
if zt in (0, 1):
|
||||
zuzhang.zhuangtai = zt
|
||||
if zt != old_zhuangtai:
|
||||
zt_map = {0: '禁用', 1: '正常'}
|
||||
base_changes.append(f'状态:{zt_map.get(old_zhuangtai, old_zhuangtai)}→{zt_map.get(zt, zt)}')
|
||||
except:
|
||||
pass
|
||||
if nickname:
|
||||
@@ -3834,9 +4026,23 @@ class UpdateZuzhangView(APIView):
|
||||
else:
|
||||
boss.nickname = nickname
|
||||
boss.save()
|
||||
if nickname != old_nickname:
|
||||
base_changes.append(f'昵称:{old_nickname or "无"}→{nickname}')
|
||||
if avatar:
|
||||
user.Avatar = avatar
|
||||
user.save()
|
||||
base_changes.append('更新了头像')
|
||||
if base_changes:
|
||||
zuzhang.save()
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_ZUZHANG,
|
||||
qitashuoming=(
|
||||
f'【后台】修改组长基础信息:{";".join(base_changes)},'
|
||||
f'组长ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
# 组长表没有电话/微信字段,如需存储可暂存到User或忽略
|
||||
# 这里不处理
|
||||
|
||||
@@ -3852,11 +4058,27 @@ class UpdateZuzhangView(APIView):
|
||||
if new_val > old_ketixian_jine:
|
||||
if '6600a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限增加可提现金额(需要6600a)'})
|
||||
action_desc = f'增加{new_val - old_ketixian_jine}元'
|
||||
elif new_val < old_ketixian_jine:
|
||||
if '6600b' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限减少可提现金额(需要6600b)'})
|
||||
zuzhang.ketixian_jine = new_val
|
||||
zuzhang.save(update_fields=['ketixian_jine'])
|
||||
action_desc = f'减少{old_ketixian_jine - new_val}元'
|
||||
else:
|
||||
action_desc = '无变动'
|
||||
if new_val != old_ketixian_jine:
|
||||
zuzhang.ketixian_jine = new_val
|
||||
zuzhang.save(update_fields=['ketixian_jine'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_ZUZHANG,
|
||||
xiugaitijiao=new_val,
|
||||
xiugaitijiaoq=old_ketixian_jine,
|
||||
qitashuoming=(
|
||||
f'【后台】修改组长可提现金额:{old_ketixian_jine}元 → {new_val}元({action_desc}),'
|
||||
f'组长ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# ---------- 3. 提现限额修改(需要6600d)----------
|
||||
kaioi_ewai = request.data.get('kaioi_ewai_tixian')
|
||||
@@ -3864,14 +4086,31 @@ class UpdateZuzhangView(APIView):
|
||||
if kaioi_ewai is not None or ewai_val is not None:
|
||||
if '6600d' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限修改提现限额(需要6600d)'})
|
||||
limit_changes = []
|
||||
old_kaioi = zuzhang.kaioi_ewai_tixian
|
||||
old_ewai = zuzhang.ewai_tixian_xiane
|
||||
if kaioi_ewai is not None:
|
||||
zuzhang.kaioi_ewai_tixian = bool(kaioi_ewai)
|
||||
if bool(kaioi_ewai) != old_kaioi:
|
||||
limit_changes.append(f'额外限额开关:{"开" if old_kaioi else "关"}→{"开" if kaioi_ewai else "关"}')
|
||||
if ewai_val is not None:
|
||||
try:
|
||||
zuzhang.ewai_tixian_xiane = Decimal(str(ewai_val))
|
||||
if zuzhang.ewai_tixian_xiane != old_ewai:
|
||||
limit_changes.append(f'额外限额金额:{old_ewai}→{zuzhang.ewai_tixian_xiane}')
|
||||
except:
|
||||
return Response({'code': 400, 'msg': '额外限额金额格式错误'})
|
||||
zuzhang.save()
|
||||
if limit_changes:
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_ZUZHANG,
|
||||
qitashuoming=(
|
||||
f'【后台】修改组长提现限额:{";".join(limit_changes)},'
|
||||
f'组长ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# ---------- 4. 分红相关修改(需要6600e)----------
|
||||
perm_enabled = request.data.get('permanent_enabled')
|
||||
@@ -3957,11 +4196,231 @@ class UpdateZuzhangView(APIView):
|
||||
if (record.cishu, record.huiyuan) not in keep_set:
|
||||
record.delete()
|
||||
|
||||
dividend_parts = []
|
||||
if perm_enabled is not None:
|
||||
dividend_parts.append(f'永久分红开关→{"开" if perm_enabled else "关"}')
|
||||
if perm_amount is not None:
|
||||
dividend_parts.append(f'永久分红金额→{perm_amount}')
|
||||
if custom_first is not None:
|
||||
dividend_parts.append(f'更新首次定制分红({len(custom_first)}项)')
|
||||
if extra_map is not None:
|
||||
dividend_parts.append(f'更新额外次数分红({len(extra_map)}组)')
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_ZUZHANG,
|
||||
qitashuoming=(
|
||||
f'【后台】修改组长分红策略:{";".join(dividend_parts) or "配置已更新"},'
|
||||
f'组长ID={yonghuid},操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
# 保存组长其他可能修改的字段(例如电话、微信没有,忽略)
|
||||
|
||||
return Response({'code': 0, 'msg': '修改成功'})
|
||||
|
||||
|
||||
class ChangeInviterView(APIView):
|
||||
"""
|
||||
后台更换邀请人/上级
|
||||
POST /houtai/htghyqr
|
||||
参数:
|
||||
username: 操作人账号
|
||||
yonghuid: 被修改用户ID
|
||||
target_type: dashou(打手)| guanshi(管事)
|
||||
new_yaoqingren: 新邀请人用户ID(须在 User 主表存在)
|
||||
权限:
|
||||
dashou → 001ee
|
||||
guanshi → 4400a
|
||||
校验:
|
||||
打手新上级须为管事;管事新上级须为组长;不可设为自己
|
||||
"""
|
||||
permission_classes = []
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
username = request.data.get('username', '').strip()
|
||||
yonghuid = request.data.get('yonghuid', '').strip()
|
||||
target_type = request.data.get('target_type', '').strip().lower()
|
||||
new_yaoqingren = request.data.get('new_yaoqingren', '').strip()
|
||||
|
||||
if not username:
|
||||
return Response({'code': 401, 'msg': '缺少username'})
|
||||
if not yonghuid:
|
||||
return Response({'code': 400, 'msg': '缺少用户ID'})
|
||||
if target_type not in ('dashou', 'guanshi'):
|
||||
return Response({'code': 400, 'msg': 'target_type 须为 dashou 或 guanshi'})
|
||||
if not new_yaoqingren:
|
||||
return Response({'code': 400, 'msg': '缺少新邀请人ID'})
|
||||
if new_yaoqingren == yonghuid:
|
||||
return Response({'code': 400, 'msg': '不能将自己设为邀请人'})
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, username)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
|
||||
if target_type == 'dashou':
|
||||
if '001ee' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限更换打手邀请人(需要001ee)'})
|
||||
else:
|
||||
if '4400a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限更换管事邀请人(需要4400a)'})
|
||||
|
||||
try:
|
||||
target_user = User.query.get(UserUID=yonghuid)
|
||||
except User.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '被修改用户不存在'})
|
||||
|
||||
try:
|
||||
inviter_user = User.query.get(UserUID=new_yaoqingren)
|
||||
except User.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '新邀请人用户ID不存在'})
|
||||
|
||||
operator = kefu.user.Phone
|
||||
|
||||
with transaction.atomic():
|
||||
if target_type == 'dashou':
|
||||
try:
|
||||
dashou = target_user.DashouProfile
|
||||
except UserDashou.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '用户不是打手'})
|
||||
try:
|
||||
guanshi_profile = inviter_user.GuanshiProfile
|
||||
except UserGuanshi.DoesNotExist:
|
||||
return Response({'code': 400, 'msg': '新邀请人不是管事,无法作为打手上级'})
|
||||
if guanshi_profile.zhuangtai != 1:
|
||||
return Response({'code': 400, 'msg': '新邀请人管事账号已禁用'})
|
||||
old_inviter = dashou.yaoqingren or '无'
|
||||
dashou.yaoqingren = new_yaoqingren
|
||||
dashou.save(update_fields=['yaoqingren'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
qitashuoming=(
|
||||
f'【后台】更换打手邀请人:{old_inviter} → {new_yaoqingren},'
|
||||
f'打手ID={yonghuid},新上级须为管事(已校验),操作人={operator}'
|
||||
),
|
||||
)
|
||||
else:
|
||||
try:
|
||||
guanshi = target_user.GuanshiProfile
|
||||
except UserGuanshi.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '用户不是管事'})
|
||||
try:
|
||||
zuzhang_profile = inviter_user.ZuzhangProfile
|
||||
except UserZuzhang.DoesNotExist:
|
||||
return Response({'code': 400, 'msg': '新邀请人不是组长,无法作为管事上级'})
|
||||
if zuzhang_profile.zhuangtai != 1:
|
||||
return Response({'code': 400, 'msg': '新邀请人组长账号已禁用'})
|
||||
old_inviter = guanshi.yaoqingren or '无'
|
||||
guanshi.yaoqingren = new_yaoqingren
|
||||
guanshi.save(update_fields=['yaoqingren'])
|
||||
write_xiugai_log(
|
||||
yonghuid=yonghuid,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_GUANSHI,
|
||||
qitashuoming=(
|
||||
f'【后台】更换管事邀请人:{old_inviter} → {new_yaoqingren},'
|
||||
f'管事ID={yonghuid},新上级须为组长(已校验),操作人={operator}'
|
||||
),
|
||||
)
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '邀请人更换成功',
|
||||
'data': {'yonghuid': yonghuid, 'new_yaoqingren': new_yaoqingren},
|
||||
})
|
||||
|
||||
|
||||
class GetOperationLogListView(APIView):
|
||||
"""
|
||||
后台操作日志列表(xiugaijilu)
|
||||
POST /houtai/hqczrz
|
||||
权限:000001 超级权限 或 czrz666
|
||||
"""
|
||||
permission_classes = []
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
username = request.data.get('username', '').strip()
|
||||
if not username:
|
||||
return Response({'code': 401, 'msg': '缺少username'})
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, username)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '000001' not in permissions and 'czrz666' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限查看操作日志(需要000001或czrz666)'})
|
||||
|
||||
yonghuid = request.data.get('yonghuid', '').strip()
|
||||
xiugaiid = request.data.get('xiugaiid', '').strip()
|
||||
leixing = request.data.get('leixing')
|
||||
keyword = request.data.get('keyword', '').strip()
|
||||
try:
|
||||
page = max(1, int(request.data.get('page', 1)))
|
||||
except (ValueError, TypeError):
|
||||
page = 1
|
||||
try:
|
||||
page_size = min(100, max(1, int(request.data.get('page_size', 20))))
|
||||
except (ValueError, TypeError):
|
||||
page_size = 20
|
||||
|
||||
qs = Xiugaijilu.query.all().order_by('-CreateTime')
|
||||
if yonghuid:
|
||||
qs = qs.filter(yonghuid=yonghuid)
|
||||
if xiugaiid:
|
||||
qs = qs.filter(xiugaiid__icontains=xiugaiid)
|
||||
if leixing not in (None, ''):
|
||||
try:
|
||||
qs = qs.filter(leixing=int(leixing))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if keyword:
|
||||
qs = qs.filter(qitashuoming__icontains=keyword)
|
||||
|
||||
total = qs.count()
|
||||
start = (page - 1) * page_size
|
||||
records = qs[start:start + page_size]
|
||||
|
||||
def _fmt_decimal(val):
|
||||
if val is None:
|
||||
return None
|
||||
return str(val)
|
||||
|
||||
data_list = []
|
||||
for r in records:
|
||||
data_list.append({
|
||||
'id': r.id,
|
||||
'yonghuid': r.yonghuid,
|
||||
'xiugaiid': r.xiugaiid,
|
||||
'leixing': r.leixing,
|
||||
'leixing_label': XIUGAI_LEIXING_LABEL.get(r.leixing, f'类型{r.leixing}'),
|
||||
'xiugaitijiao': _fmt_decimal(r.xiugaitijiao),
|
||||
'xiugaitijiaoq': _fmt_decimal(r.xiugaitijiaoq),
|
||||
'jifen': r.jifen,
|
||||
'yjifen': r.yjifen,
|
||||
'yajin': _fmt_decimal(r.yajin),
|
||||
'yyajin': _fmt_decimal(r.yyajin),
|
||||
'shangjiayue': _fmt_decimal(r.shangjiayue),
|
||||
'shangjiayueq': _fmt_decimal(r.shangjiayueq),
|
||||
'guanshiyue': _fmt_decimal(r.guanshiyue),
|
||||
'guanshiyueq': _fmt_decimal(r.guanshiyueq),
|
||||
'huiyuants': r.huiyuants,
|
||||
'huiyuan_id': r.huiyuan_id,
|
||||
'qitashuoming': r.qitashuoming or '',
|
||||
'create_time': r.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if r.CreateTime else '',
|
||||
})
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
'list': data_list,
|
||||
'total': total,
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
class GetProductTypeZoneView(APIView):
|
||||
|
||||
Reference in New Issue
Block a user