feat(jituan): 集团多俱乐部改造 — club 隔离、财务/提现/分红/展示配置

This commit is contained in:
XingQue
2026-06-24 05:02:18 +08:00
parent ce9b09f096
commit dcc4936428
82 changed files with 5748 additions and 924 deletions

View File

@@ -21,6 +21,16 @@ from gvsdsdk.fluent import db, func, FQ
logger = logging.getLogger(__name__)
def _club_id_for_yonghuid(yonghuid, club_id=None):
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.club_user import get_user_club_id
from users.business_models import User
if club_id:
return club_id
u = User.query.filter(UserUID=yonghuid).first()
return get_user_club_id(u) if u else CLUB_ID_DEFAULT
def _get_real_ip(request):
"""获取真实IP考虑代理"""
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
@@ -150,26 +160,24 @@ def verify_kefu_permission(request, username_from_frontend=None):
def update_dashou_daily_by_action(yonghuid, amount, action):
def update_dashou_daily_by_action(yonghuid, amount, action, club_id=None):
"""
根据行为类型更新打手每日统计(接单、成交、退款)
参数:
yonghuid: 打手用户ID
amount: 本单涉及的金额Decimal
action: 1 = 接单, 2 = 成交(结算), 3 = 退款
"""
amount = Decimal(str(amount)) if amount else Decimal('0.00')
if amount <= 0:
return # 金额非正不统计
return
cid = _club_id_for_yonghuid(yonghuid, club_id)
today = date.today()
with transaction.atomic():
stat, created = PlayerDailyStats.objects.select_for_update().get_or_create(
club_id=cid,
PlayerID=yonghuid,
Date=today,
defaults={
'club_id': cid,
'PlayerID': yonghuid,
'Date': today,
'AcceptedOrderTotal': 0,
@@ -198,33 +206,24 @@ def update_dashou_daily_by_action(yonghuid, amount, action):
PlayerDailyStats.query.filter(id=stat.id).update(**update_fields)
def update_shangjia_daily(yonghuid, amount, action, order_id=None):
def update_shangjia_daily(yonghuid, amount, action, order_id=None, club_id=None):
"""
根据操作行为更新商家每日统计(派发、结算、退款)
参数:
yonghuid: 商家用户ID
amount: 当前订单涉及的金额Decimal
action: 操作类型1 = 派发2 = 结算成交3 = 退款
order_id: 订单ID传入时同步更新该订单派单归属客服的日统计
说明:
- 金额必须大于0否则不执行任何操作
- 使用 select_for_update + F() 表达式保证原子性和并发安全
- 每天每个商家只会有一条统计记录,不存在则自动创建
"""
amount = Decimal(str(amount)) if amount else Decimal('0.00')
if amount <= 0:
return # 金额非正,不统计
return
cid = _club_id_for_yonghuid(yonghuid, club_id)
today = date.today()
with transaction.atomic():
# 获取或创建当天统计记录,同时加锁防止并发
stat, created = MerchantDailyStats.objects.select_for_update().get_or_create(
club_id=cid,
MerchantID=yonghuid,
Date=today,
defaults={
'club_id': cid,
'MerchantID': yonghuid,
'Date': today,
'AssignedOrderCount': 0,
@@ -262,18 +261,20 @@ def update_shangjia_daily(yonghuid, amount, action, order_id=None):
logger.warning('同步客服日统计失败 order_id=%s', order_id, exc_info=True)
def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00'), club_id=None):
"""
根据操作行为更新管事每日统计(邀请打手、充值会员、订单/押金分红)
action: 1 = 邀请打手, 2 = 充值会员, 3 = 商家订单分红, 4 = 押金分红
"""
cid = _club_id_for_yonghuid(yonghuid, club_id)
today = date.today()
with transaction.atomic():
stat, created = ManagerDailyStats.objects.select_for_update().get_or_create(
club_id=cid,
ManagerID=yonghuid,
Date=today,
defaults={
'club_id': cid,
'ManagerID': yonghuid,
'Date': today,
'InvitedPlayerCount': 0,
@@ -319,17 +320,17 @@ def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
)
def update_guanshi_xufei_daily(yonghuid, xufei_jine=Decimal('0.00')):
"""
管事续费统计(单独表)
用法: update_guanshi_xufei_daily('300001', Decimal('30'))
"""
def update_guanshi_xufei_daily(yonghuid, xufei_jine=Decimal('0.00'), club_id=None):
"""管事续费统计(单独表)"""
cid = _club_id_for_yonghuid(yonghuid, club_id)
today = date.today()
with transaction.atomic():
stat, created = ManagerRenewalDailyStats.objects.select_for_update().get_or_create(
club_id=cid,
ManagerID=yonghuid,
Date=today,
defaults={
'club_id': cid,
'ManagerID': yonghuid,
'Date': today,
'RenewalTotal': 1,
@@ -343,24 +344,18 @@ def update_guanshi_xufei_daily(yonghuid, xufei_jine=Decimal('0.00')):
)
def update_zuzhang_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
"""
根据操作行为更新组长每日统计(邀请管事、分佣收入)
参数:
yonghuid: 组长用户ID
action: 操作类型
1 = 邀请管事(次数+1无金额
2 = 分佣收入(累加金额)
amount: 分佣金额Decimal仅在 action=2 时有效
"""
def update_zuzhang_daily_by_action(yonghuid, action, amount=Decimal('0.00'), club_id=None):
"""根据操作行为更新组长每日统计"""
cid = _club_id_for_yonghuid(yonghuid, club_id)
today = date.today()
with transaction.atomic():
stat, created = LeaderDailyStats.objects.select_for_update().get_or_create(
club_id=cid,
LeaderID=yonghuid,
Date=today,
defaults={
'club_id': cid,
'LeaderID': yonghuid,
'Date': today,
'InvitedManagerCount': 0,
@@ -394,23 +389,22 @@ def update_zuzhang_daily_by_action(yonghuid, action, amount=Decimal('0.00')):
def update_tixian_daily_stat(leixing, amount):
def update_tixian_daily_stat(leixing, amount, club_id=None):
"""
更新每日提现统计(平台维度)
更新每日提现统计(平台维度,按俱乐部
leixing: 1=打手, 2=管事, 3=组长
amount: 本次提现金额(申请金额,含手续费)
"""
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.withdraw_config import get_or_create_platform_daily_stat
club_id = (club_id or '').strip() or CLUB_ID_DEFAULT
today = date.today()
with transaction.atomic():
stat, created = WithdrawalDailyStats.objects.select_for_update().get_or_create(
Date=today,
WithdrawalType=leixing,
defaults={'total_amount': amount}
stat = get_or_create_platform_daily_stat(club_id, leixing, today)
WithdrawalDailyStats.query.filter(id=stat.id).update(
total_amount=F('total_amount') + amount
)
if not created:
WithdrawalDailyStats.query.filter(id=stat.id).update(
total_amount=F('total_amount') + amount
)
# 罚款权限(与 permission 表一致)
@@ -561,13 +555,14 @@ XIUGAI_LEIXING_LABEL = {
}
def write_xiugai_log(*, yonghuid, xiugaiid, leixing, qitashuoming, **extra_fields):
def write_xiugai_log(*, yonghuid, xiugaiid, leixing, qitashuoming, club_id=None, request_ip='', **extra_fields):
"""
统一写入 xiugaijilu 修改记录。
qitashuoming 应详细描述本次操作(尤其是金额、身份、上下级变更等)。
extra_fields 可传入 xiugaitijiao、shangjiayue、guanshiyue 等模型字段。
"""
from users.models import Xiugaijilu
from jituan.services.admin_audit import log_admin_audit_from_xiugai
if not qitashuoming:
label = XIUGAI_LEIXING_LABEL.get(leixing, f'类型{leixing}')
@@ -579,4 +574,12 @@ def write_xiugai_log(*, yonghuid, xiugaiid, leixing, qitashuoming, **extra_field
leixing=leixing,
qitashuoming=qitashuoming,
**extra_fields,
)
log_admin_audit_from_xiugai(
yonghuid=yonghuid,
xiugaiid=xiugaiid,
leixing=leixing,
qitashuoming=qitashuoming,
club_id=club_id,
request_ip=request_ip,
)