Files
Django/merchant_ops/services/dispatch.py

204 lines
7.7 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_huiyuan_id = str(huiyuan_id) if huiyuan_id else ''
except ValueError:
final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1
final_huiyuan_id = str(huiyuan_id) if huiyuan_id else ''
else:
final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1
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}
if jiage > float(shangjia.yue):
return False, {'code': 400, 'msg': f'商家余额不足,当前{shangjia.yue}', '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,
yue=F('yue') - Decimal(str(jiage)),
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)},
}