208 lines
7.8 KiB
Python
208 lines
7.8 KiB
Python
"""子客服派单(独立实现,不修改商家派单接口)。"""
|
|
import logging
|
|
import os
|
|
import random
|
|
import time
|
|
from decimal import Decimal
|
|
|
|
from django.db import transaction
|
|
from django.db.models import F
|
|
|
|
from backend.utils import update_shangjia_daily
|
|
from merchant_ops.constants import ACTOR_STAFF, STAT_ACTION_DISPATCH
|
|
from merchant_ops.models import MerchantOrderDispatch
|
|
from merchant_ops.services.wallet import check_wallet_available, confirm_dispatch_deduct
|
|
from orders.models import MerchantOrderExt, Order
|
|
from orders.notice_tasks import dingdan_guangbo
|
|
from orders.utils import calc_shangjia_order_fencheng
|
|
from products.models import ShangpinLeixing
|
|
from rank.models import Chenghao, DingdanBiaoqian
|
|
from users.models import UserShangjia, UserDashou
|
|
from users.business_models import User
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _generate_dingdan_id():
|
|
ts = int(time.time() * 1000)
|
|
pid = os.getpid() % 1000
|
|
rnd = random.randint(1000, 9999)
|
|
return f"SJ{ts}{pid:03d}{rnd}"
|
|
|
|
|
|
def staff_dispatch_order(member, staff_user, data):
|
|
"""
|
|
子客服发单。返回 (success, payload_dict)
|
|
payload_dict: code/msg/data 或 dingdan
|
|
"""
|
|
shangpin_type_id = data.get('shangpinTypeId')
|
|
huiyuan_id = data.get('huiyuanId')
|
|
dingdan_jieshao = str(data.get('dingdanJieshao', '')).strip()
|
|
dingdan_beizhu = str(data.get('dingdanBeizhu', '')).strip()
|
|
laoban_name = str(data.get('laobanName', '')).strip()
|
|
zhiding_uid = str(data.get('zhidingUid', '')).strip()
|
|
jiage_str = data.get('jiage')
|
|
label_id = data.get('labelId')
|
|
commission_enabled = data.get('commissionEnabled', False)
|
|
commission_value_raw = data.get('commissionValue')
|
|
commission_value_str = str(commission_value_raw).strip() if commission_value_raw is not None else ''
|
|
|
|
if not all([shangpin_type_id, dingdan_jieshao, laoban_name, jiage_str]):
|
|
return False, {'code': 400, 'msg': '缺少必填参数', 'data': None}
|
|
|
|
try:
|
|
jiage = float(jiage_str)
|
|
if jiage < 1 or jiage > 10000:
|
|
return False, {'code': 400, 'msg': '价格需在1-10000元之间', 'data': None}
|
|
except ValueError:
|
|
return False, {'code': 400, 'msg': '价格格式错误', 'data': None}
|
|
|
|
try:
|
|
shangpin_type = ShangpinLeixing.query.get(id=shangpin_type_id)
|
|
except ShangpinLeixing.DoesNotExist:
|
|
return False, {'code': 400, 'msg': '商品类型不存在', 'data': None}
|
|
|
|
if commission_enabled and commission_value_str:
|
|
try:
|
|
cv = float(commission_value_str)
|
|
if cv > 0:
|
|
final_yaoqiu_type = 2
|
|
final_yongjin = Decimal(str(cv))
|
|
final_huiyuan_id = ''
|
|
else:
|
|
final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1
|
|
final_yongjin = None
|
|
final_huiyuan_id = str(huiyuan_id) if huiyuan_id else ''
|
|
except ValueError:
|
|
final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1
|
|
final_yongjin = None
|
|
final_huiyuan_id = str(huiyuan_id) if huiyuan_id else ''
|
|
else:
|
|
final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1
|
|
final_yongjin = None
|
|
final_huiyuan_id = str(huiyuan_id) if huiyuan_id else ''
|
|
|
|
chenghao_obj = None
|
|
label_id_str = str(label_id).strip() if label_id is not None else ''
|
|
if label_id_str and label_id_str not in ('0', 'null', 'undefined'):
|
|
try:
|
|
lid = int(label_id_str)
|
|
if lid > 0:
|
|
chenghao_obj = Chenghao.query.filter(id=lid).first()
|
|
except (ValueError, TypeError):
|
|
pass
|
|
|
|
merchant_id = member.merchant_id
|
|
try:
|
|
shangjia = UserShangjia.query.get(user__UserUID=merchant_id)
|
|
except UserShangjia.DoesNotExist:
|
|
return False, {'code': 403, 'msg': '所属商家不存在', 'data': None}
|
|
|
|
if shangjia.zhuangtai != 1:
|
|
return False, {'code': 403, 'msg': '商家状态异常', 'data': None}
|
|
|
|
try:
|
|
check_wallet_available(member, jiage)
|
|
except ValueError as e:
|
|
return False, {'code': 400, 'msg': str(e), 'data': None}
|
|
|
|
zhiding_dashou = None
|
|
if zhiding_uid:
|
|
try:
|
|
zhiding_user = User.query.get(UserUID=zhiding_uid)
|
|
zhiding_dashou = zhiding_user.DashouProfile
|
|
if zhiding_dashou.zhanghaozhuangtai != 1:
|
|
return False, {'code': 400, 'msg': '指定打手状态异常', 'data': None}
|
|
except User.DoesNotExist:
|
|
return False, {'code': 400, 'msg': '指定用户不存在', 'data': None}
|
|
except UserDashou.DoesNotExist:
|
|
return False, {'code': 400, 'msg': '指定用户不是打手', 'data': None}
|
|
|
|
dashou_fencheng, guanshi_fencheng = calc_shangjia_order_fencheng(jiage)
|
|
merchant_user = User.query.get(UserUID=merchant_id)
|
|
|
|
dingdan = None
|
|
try:
|
|
with transaction.atomic():
|
|
check_wallet_available(member, jiage)
|
|
|
|
dingdan = Order.query.create(
|
|
OrderID=_generate_dingdan_id(),
|
|
Status=7 if zhiding_dashou else 1,
|
|
Platform=2,
|
|
Amount=jiage,
|
|
PlayerCommission=dashou_fencheng,
|
|
ManagerCommission=guanshi_fencheng,
|
|
AssignedID=zhiding_uid if zhiding_dashou else '',
|
|
ProductID=0,
|
|
ProductTypeID=int(shangpin_type_id),
|
|
GrabRequirement=final_yaoqiu_type,
|
|
CommissionReq=final_yongjin,
|
|
MembershipID=final_huiyuan_id,
|
|
Description=dingdan_jieshao[:2000],
|
|
Remark=dingdan_beizhu[:1000],
|
|
Nickname=laoban_name[:50],
|
|
ImageURL=merchant_user.Avatar if merchant_user else '',
|
|
User1ID=f"Sj{merchant_id}",
|
|
)
|
|
|
|
MerchantOrderExt.query.create(
|
|
Order=dingdan,
|
|
MerchantID=merchant_id,
|
|
MerchantNickname=shangjia.nicheng,
|
|
)
|
|
|
|
if chenghao_obj:
|
|
DingdanBiaoqian.query.create(dingdan=dingdan, chenghao=chenghao_obj)
|
|
|
|
UserShangjia.query.filter(id=shangjia.id).update(
|
|
fabu=F('fabu') + 1,
|
|
jinridingdan=F('jinridingdan') + 1,
|
|
jinriliushui=F('jinriliushui') + Decimal(str(jiage)),
|
|
jinyuedingdan=F('jinyuedingdan') + 1,
|
|
jinyueliushui=F('jinyueliushui') + Decimal(str(jiage)),
|
|
)
|
|
|
|
MerchantOrderDispatch.objects.create(
|
|
order_id=dingdan.OrderID,
|
|
merchant_id=merchant_id,
|
|
dispatch_actor_type=ACTOR_STAFF,
|
|
dispatch_actor_id=member.staff_user_id,
|
|
staff_member_id=member.id,
|
|
)
|
|
|
|
confirm_dispatch_deduct(member, jiage, dingdan.OrderID, member.staff_user_id)
|
|
update_shangjia_daily(
|
|
merchant_id, Decimal(str(jiage)), STAT_ACTION_DISPATCH,
|
|
order_id=dingdan.OrderID,
|
|
)
|
|
|
|
except ValueError as e:
|
|
return False, {'code': 400, 'msg': str(e), 'data': None}
|
|
except Exception as e:
|
|
logger.error(f'子客服派单失败: {e}', exc_info=True)
|
|
return False, {'code': 500, 'msg': '订单创建失败', 'data': None}
|
|
|
|
try:
|
|
from orders.views import ShangjiaPaifaView
|
|
view = ShangjiaPaifaView()
|
|
game_type = view._get_game_type_name(dingdan.ProductTypeID)
|
|
except Exception:
|
|
game_type = '游戏订单'
|
|
|
|
try:
|
|
dingdan_guangbo.delay({
|
|
'OrderID': dingdan.OrderID,
|
|
'game_type': game_type,
|
|
'amount': str(dingdan.Amount),
|
|
'order_desc': (dingdan.Description or '')[:50],
|
|
})
|
|
except Exception as e:
|
|
logger.error(f'广播任务失败: {e}')
|
|
|
|
return True, {
|
|
'code': 200,
|
|
'msg': '派单成功',
|
|
'data': {'dingdan_id': dingdan.OrderID, 'jine': str(dingdan.Amount)},
|
|
}
|