feat: 打手赠送会员(免费接单)独立表与抢单资格

新增 dashou_zengsong_huiyuan,与购买会员分离;抢单/抢单池认赠送有效会员;后台送/改期/移除接口,送时积分非10则改为10并写操作日志。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-17 02:14:07 +08:00
parent a1a49261a5
commit cb89720260
7 changed files with 538 additions and 3 deletions

View File

@@ -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': '移除成功'})