feat: 打手赠送会员(免费接单)独立表与抢单资格
新增 dashou_zengsong_huiyuan,与购买会员分离;抢单/抢单池认赠送有效会员;后台送/改期/移除接口,送时积分非10则改为10并写操作日志。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -304,6 +304,7 @@ class KefuGetDashouDetailView(APIView):
|
||||
'data': {
|
||||
'user_info': user_info,
|
||||
'member_list': member_list,
|
||||
'gift_member_list': [],
|
||||
'all_members': all_members,
|
||||
'permissions': permissions,
|
||||
}
|
||||
@@ -369,11 +370,15 @@ class KefuGetDashouDetailView(APIView):
|
||||
# 7. 查询所有会员类型(用于前端添加会员)
|
||||
all_members = list(Huiyuan.query.all().values('huiyuan_id', 'jieshao'))
|
||||
|
||||
from jituan.services.gift_huiyuan import list_gift_huiyuan_for_admin
|
||||
gift_member_list = list_gift_huiyuan_for_admin(uid)
|
||||
|
||||
return Response({
|
||||
'code': 0,
|
||||
'data': {
|
||||
'user_info': user_info,
|
||||
'member_list': member_list,
|
||||
'gift_member_list': gift_member_list,
|
||||
'all_members': all_members,
|
||||
'permissions': permissions, # 返回当前客服的权限列表
|
||||
}
|
||||
@@ -1150,6 +1155,223 @@ class KefuChatPermissionsView(APIView):
|
||||
})
|
||||
|
||||
|
||||
class DashouGiftHuiyuanSaveView(APIView):
|
||||
"""
|
||||
赠送会员 / 改期(免费接单资格,写入 dashou_zengsong_huiyuan)
|
||||
POST /houtai/dszsonghy
|
||||
Body: {
|
||||
phone, dashou_id, huiyuan_id,
|
||||
daoqi_time: 'YYYY-MM-DD' 或 'YYYY-MM-DD HH:MM:SS',
|
||||
id?: 已有记录ID(改期时建议传)
|
||||
}
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
from jituan.services.gift_huiyuan import (
|
||||
has_gift_huiyuan_permission,
|
||||
parse_gift_daoqi_time,
|
||||
upsert_gift_huiyuan,
|
||||
update_gift_huiyuan_daoqi,
|
||||
)
|
||||
from products.models import Huiyuan as HuiyuanModel
|
||||
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
dashou_id = (request.data.get('dashou_id') or request.data.get('uid') or '').strip()
|
||||
huiyuan_id = (request.data.get('huiyuan_id') or '').strip()
|
||||
record_id = request.data.get('id')
|
||||
raw_daoqi = request.data.get('daoqi_time')
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, phone or None)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if not has_gift_huiyuan_permission(permissions):
|
||||
return Response({'code': 403, 'msg': '无赠送会员权限(需打手基础管理或加积分权限)'})
|
||||
|
||||
if not dashou_id:
|
||||
return Response({'code': 400, 'msg': '缺少打手ID'})
|
||||
daoqi_time, err = parse_gift_daoqi_time(raw_daoqi)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
|
||||
try:
|
||||
dashou_user = User.query.get(UserUID=dashou_id)
|
||||
except User.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '打手不存在'})
|
||||
denied = forbid_if_user_out_of_scope(request, dashou_user)
|
||||
if denied:
|
||||
return denied
|
||||
try:
|
||||
dashou_user.DashouProfile
|
||||
except ObjectDoesNotExist:
|
||||
return Response({'code': 404, 'msg': '该用户不是打手'})
|
||||
|
||||
song_ren = getattr(kefu.user, 'Phone', None) or phone
|
||||
operator = song_ren
|
||||
|
||||
# 有记录ID:只改期
|
||||
if record_id not in (None, ''):
|
||||
try:
|
||||
rid = int(record_id)
|
||||
except (TypeError, ValueError):
|
||||
return Response({'code': 400, 'msg': '无效的记录ID'})
|
||||
rec, err = update_gift_huiyuan_daoqi(
|
||||
record_id=rid,
|
||||
yonghu_id=dashou_id,
|
||||
daoqi_time=daoqi_time,
|
||||
song_ren=song_ren,
|
||||
)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
try:
|
||||
hy_name = HuiyuanModel.query.get(huiyuan_id=rec.huiyuan_id).jieshao
|
||||
except HuiyuanModel.DoesNotExist:
|
||||
hy_name = rec.huiyuan_id
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
huiyuan_id=rec.huiyuan_id,
|
||||
qitashuoming=(
|
||||
f'【后台】修改赠送会员到期时间:会员ID={rec.huiyuan_id}({hy_name}),'
|
||||
f'新到期={rec.daoqi_time.strftime("%Y-%m-%d %H:%M:%S")},'
|
||||
f'打手ID={dashou_id},操作人={operator}'
|
||||
),
|
||||
)
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '改期成功',
|
||||
'data': {
|
||||
'id': rec.id,
|
||||
'huiyuan_id': rec.huiyuan_id,
|
||||
'daoqi_time': rec.daoqi_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
},
|
||||
})
|
||||
|
||||
if not huiyuan_id:
|
||||
return Response({'code': 400, 'msg': '缺少会员ID'})
|
||||
|
||||
rec, created, jifen_info, err = upsert_gift_huiyuan(
|
||||
yonghu_id=dashou_id,
|
||||
huiyuan_id=huiyuan_id,
|
||||
daoqi_time=daoqi_time,
|
||||
song_ren=song_ren,
|
||||
)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
|
||||
try:
|
||||
hy_name = HuiyuanModel.query.get(huiyuan_id=huiyuan_id).jieshao
|
||||
except HuiyuanModel.DoesNotExist:
|
||||
hy_name = huiyuan_id
|
||||
|
||||
if jifen_info:
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
jifen=jifen_info['after'],
|
||||
yjifen=jifen_info['before'],
|
||||
qitashuoming=(
|
||||
f'【后台】送会员时整改积分:{jifen_info["before"]} → {jifen_info["after"]},'
|
||||
f'原积分={jifen_info["before"]},整改后={jifen_info["after"]},'
|
||||
f'打手ID={dashou_id},操作人={operator}(送会员免费接单)'
|
||||
),
|
||||
)
|
||||
|
||||
action_label = '赠送' if created else '更新到期时间'
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
huiyuan_id=huiyuan_id,
|
||||
qitashuoming=(
|
||||
f'【后台】{action_label}赠送会员(免费接单):会员ID={huiyuan_id}({hy_name}),'
|
||||
f'到期={rec.daoqi_time.strftime("%Y-%m-%d %H:%M:%S")},'
|
||||
f'打手ID={dashou_id},操作人={operator}(写入赠送会员表,非购买会员)'
|
||||
),
|
||||
)
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '赠送成功' if created else '到期时间已更新',
|
||||
'data': {
|
||||
'id': rec.id,
|
||||
'huiyuan_id': rec.huiyuan_id,
|
||||
'daoqi_time': rec.daoqi_time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'created': created,
|
||||
'jifen_adjusted': bool(jifen_info),
|
||||
'jifen': jifen_info,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
class DashouGiftHuiyuanRemoveView(APIView):
|
||||
"""
|
||||
移除赠送会员
|
||||
POST /houtai/dsycsonghy
|
||||
Body: { phone, dashou_id, id? , huiyuan_id? }
|
||||
"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
from jituan.services.gift_huiyuan import (
|
||||
has_gift_huiyuan_permission,
|
||||
remove_gift_huiyuan,
|
||||
)
|
||||
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
dashou_id = (request.data.get('dashou_id') or request.data.get('uid') or '').strip()
|
||||
record_id = request.data.get('id')
|
||||
huiyuan_id = (request.data.get('huiyuan_id') or '').strip()
|
||||
|
||||
kefu, permissions = verify_kefu_permission(request, phone or None)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if not has_gift_huiyuan_permission(permissions):
|
||||
return Response({'code': 403, 'msg': '无移除赠送会员权限'})
|
||||
|
||||
if not dashou_id:
|
||||
return Response({'code': 400, 'msg': '缺少打手ID'})
|
||||
|
||||
try:
|
||||
dashou_user = User.query.get(UserUID=dashou_id)
|
||||
except User.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '打手不存在'})
|
||||
denied = forbid_if_user_out_of_scope(request, dashou_user)
|
||||
if denied:
|
||||
return denied
|
||||
|
||||
rid = None
|
||||
if record_id not in (None, ''):
|
||||
try:
|
||||
rid = int(record_id)
|
||||
except (TypeError, ValueError):
|
||||
return Response({'code': 400, 'msg': '无效的记录ID'})
|
||||
|
||||
ok, err = remove_gift_huiyuan(
|
||||
record_id=rid,
|
||||
yonghu_id=dashou_id if not rid else None,
|
||||
huiyuan_id=huiyuan_id if not rid else None,
|
||||
)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
|
||||
operator = getattr(kefu.user, 'Phone', None) or phone
|
||||
write_xiugai_log(
|
||||
yonghuid=dashou_id,
|
||||
xiugaiid=operator,
|
||||
leixing=XIUGAI_LEIXING_DASHOU,
|
||||
huiyuan_id=huiyuan_id or '',
|
||||
qitashuoming=(
|
||||
f'【后台】移除赠送会员(免费接单):记录ID={rid or "-"},'
|
||||
f'会员ID={huiyuan_id or "-"},打手ID={dashou_id},操作人={operator}'
|
||||
),
|
||||
)
|
||||
return Response({'code': 0, 'msg': '移除成功'})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user