进行了 backend 的重构,实验中

This commit is contained in:
2026-06-18 04:15:23 +08:00
parent 54cc658f0b
commit 854c832c07
10 changed files with 1196 additions and 864 deletions

View File

@@ -12,10 +12,10 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from backend.models import (
DashouRiTongji,
GuanshiRiTongji,
ZuzhangRiTongji,
ShangjiaRiTongji,
PlayerDailyStats,
ManagerDailyStats,
LeaderDailyStats,
MerchantDailyStats,
)
from users.models import UserDashou, UserShangjia, UserBoss
from gvsdsdk.models import User
@@ -29,28 +29,32 @@ SHENFEN_OPTIONS = frozenset({'dashou', 'guanshi', 'zuzhang', 'shangjia'})
ROLE_CONFIG = {
'dashou': {
'model': DashouRiTongji,
'sort_field': 'chengjiao_zonge',
'fields': ('jiedan_zongliang', 'chengjiao_zongliang', 'jiedan_zonge', 'chengjiao_zonge'),
'int_fields': frozenset({'jiedan_zongliang', 'chengjiao_zongliang'}),
'model': PlayerDailyStats,
'id_field': 'PlayerID',
'sort_field': 'CompletedAmount',
'fields': ('AcceptedOrderTotal', 'CompletedOrderTotal', 'AcceptedAmount', 'CompletedAmount'),
'int_fields': frozenset({'AcceptedOrderTotal', 'CompletedOrderTotal'}),
},
'guanshi': {
'model': GuanshiRiTongji,
'sort_field': 'shouru_zonge',
'fields': ('yaoqing_dashou_shu', 'chongzhi_dashou_shu', 'shouru_zonge'),
'int_fields': frozenset({'yaoqing_dashou_shu', 'chongzhi_dashou_shu'}),
'model': ManagerDailyStats,
'id_field': 'ManagerID',
'sort_field': 'TotalIncome',
'fields': ('InvitedPlayerCount', 'RechargedPlayerCount', 'TotalIncome'),
'int_fields': frozenset({'InvitedPlayerCount', 'RechargedPlayerCount'}),
},
'zuzhang': {
'model': ZuzhangRiTongji,
'sort_field': 'shouru_zonge',
'fields': ('yaoqing_guanshi_shu', 'fenyong_jine', 'shouru_zonge'),
'int_fields': frozenset({'yaoqing_guanshi_shu'}),
'model': LeaderDailyStats,
'id_field': 'LeaderID',
'sort_field': 'TotalIncome',
'fields': ('InvitedManagerCount', 'CommissionAmount', 'TotalIncome'),
'int_fields': frozenset({'InvitedManagerCount'}),
},
'shangjia': {
'model': ShangjiaRiTongji,
'sort_field': 'jiesuan_jine',
'fields': ('paifa_dingdan_shu', 'paifa_jine', 'jiesuan_dingdan_shu', 'jiesuan_jine'),
'int_fields': frozenset({'paifa_dingdan_shu', 'jiesuan_dingdan_shu'}),
'model': MerchantDailyStats,
'id_field': 'MerchantID',
'sort_field': 'SettledAmount',
'fields': ('AssignedOrderCount', 'AssignedAmount', 'SettledOrderCount', 'SettledAmount'),
'int_fields': frozenset({'AssignedOrderCount', 'SettledOrderCount'}),
},
}
@@ -137,10 +141,11 @@ class PhbHqsjView(APIView):
nick_map, avatar_map = self._load_user_display(rows, shenfen)
cfg = ROLE_CONFIG[shenfen]
int_fields = cfg['int_fields']
id_field = cfg['id_field']
result_list = []
for idx, row in enumerate(rows):
yonghuid = row['yonghuid']
yonghuid = row[id_field]
item = {
'mingci': idx + 1,
'yonghuid': yonghuid,
@@ -169,35 +174,37 @@ class PhbHqsjView(APIView):
model = cfg['model']
sort_field = cfg['sort_field']
fields = cfg['fields']
id_field = cfg['id_field']
annotate_kwargs = {f: Sum(f) for f in fields}
if all_time:
rows = (
model.objects
.values('yonghuid')
.values(id_field)
.annotate(**annotate_kwargs)
.order_by(f'-{sort_field}')[:MAX_RANK]
)
return list(rows)
if start_date == end_date:
qs = model.objects.filter(riqi=start_date).order_by(f'-{sort_field}')[:MAX_RANK]
qs = model.objects.filter(Date=start_date).order_by(f'-{sort_field}')[:MAX_RANK]
return [
{'yonghuid': r.yonghuid, **{f: getattr(r, f) for f in fields}}
{id_field: getattr(r, id_field), **{f: getattr(r, f) for f in fields}}
for r in qs
]
rows = (
model.objects
.filter(riqi__gte=start_date, riqi__lte=end_date)
.values('yonghuid')
.filter(Date__gte=start_date, Date__lte=end_date)
.values(id_field)
.annotate(**annotate_kwargs)
.order_by(f'-{sort_field}')[:MAX_RANK]
)
return list(rows)
def _load_user_display(self, rows, shenfen):
yonghuids = [r['yonghuid'] for r in rows if r.get('yonghuid')]
id_field = ROLE_CONFIG[shenfen]['id_field']
yonghuids = [r[id_field] for r in rows if r.get(id_field)]
if not yonghuids:
return {}, {}

View File

@@ -31,7 +31,7 @@ from config.models import Szjilu, TixianQuotaDefault
from utils.fadan_utils import check_fadan_qiangdan_eligible
from products.models import Huiyuangoumai
from backend.models import TixianRiTongji
from backend.models import WithdrawalDailyStats
from utils.wechat_v3 import build_authorization
@@ -445,12 +445,12 @@ def _get_active_auto_record(shenhe_danhao):
def _get_platform_daily_total(leixing, today=None):
"""平台今日已提现总额:只读 houtai.TixianRiTongji(到账金额口径)"""
"""平台今日已提现总额:只读 houtai.WithdrawalDailyStats(到账金额口径)"""
if today is None:
today = date.today()
try:
return TixianRiTongji.query.get(riqi=today, leixing=leixing).total_amount
except TixianRiTongji.DoesNotExist:
return WithdrawalDailyStats.query.get(Date=today, WithdrawalType=leixing).total_amount
except WithdrawalDailyStats.DoesNotExist:
return decimal.Decimal('0.00')
@@ -576,7 +576,7 @@ def check_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe_d
def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe_danhao=''):
"""
收款前原子预占每日限额(必须在 transaction.atomic 内调用)。
锁定 TixianRiTongji + 用户行,校验通过后立即写入统计,防止高并发超额。
锁定 WithdrawalDailyStats + 用户行,校验通过后立即写入统计,防止高并发超额。
本审核单已有进行中/成功打款记录则视为已预占,不重复加计。
返回 (True, '', '') 或 (False, msg, 'personal'|'platform')
"""
@@ -617,9 +617,9 @@ def reserve_collect_quota_limits(user_main, leixing, jine, shijidaozhang, shenhe
'personal',
)
platform_stat, _ = TixianRiTongji.objects.select_for_update().get_or_create(
riqi=today,
leixing=leixing,
platform_stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
Date=today,
WithdrawalType=leixing,
defaults={'total_amount': decimal.Decimal('0.00')},
)
platform_limit = _get_platform_daily_limit(leixing)
@@ -678,15 +678,15 @@ def release_collect_quota_reservation(user_main, leixing, jine, shijidaozhang):
zuzhang.save(update_fields=['jinri_tixian'])
try:
stat = TixianRiTongji.objects.select_for_update().get(
riqi=today, leixing=leixing,
stat = WithdrawalDailyStats.objects.select_for_update().get(
Date=today, WithdrawalType=leixing,
)
stat.total_amount = max(
stat.total_amount - shijidaozhang,
decimal.Decimal('0.00'),
)
stat.save(update_fields=['total_amount'])
except TixianRiTongji.DoesNotExist:
except WithdrawalDailyStats.DoesNotExist:
pass
except Exception as e:
logger.error(
@@ -741,7 +741,7 @@ def _quota_already_reserved_for_record(auto_record):
def apply_transfer_success_quota(auto_record):
"""
打款成功时累加每日限额统计(仅自动审核流程 shenhe_danhao 非空)。
- houtai.TixianRiTongji.total_amount += 实际到账
- houtai.WithdrawalDailyStats.total_amount += 实际到账
- 用户扩展表个人今日已提 += 申请金额(打手/管事/组长)
须在 transaction.atomic 内、且打款记录 zhuangtai 由 0→1 时调用一次。
"""
@@ -758,9 +758,9 @@ def apply_transfer_success_quota(auto_record):
logger.error('打款成功累加限额失败:用户不存在 %s', auto_record.yonghuid)
return
platform_stat, _ = TixianRiTongji.objects.select_for_update().get_or_create(
riqi=today,
leixing=leixing,
platform_stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
Date=today,
WithdrawalType=leixing,
defaults={'total_amount': decimal.Decimal('0.00')},
)
platform_stat.total_amount += shijidaozhang

View File

@@ -84,7 +84,7 @@ from products.models import (
ShangpinLeixing, Huiyuan, Huiyuangoumai, Gsfenhong, Czjilu
)
from config.models import Qunpeizhi, Szjilu
from backend.models import ShangjiaRiTongji
from backend.models import MerchantDailyStats
from rank.models import (
KaohePayTemp, Chenghao, ShenheJilu,
KaoheCishuFeiyong, YonghuChenghao
@@ -1088,13 +1088,13 @@ class ShangJiaXinXiView(APIView):
})
response_data['chenghao_list'] = chenghao_list
# ------------------- 3. 从 ShangjiaRiTongji 获取今日统计 -------------------
# ------------------- 3. 从 MerchantDailyStats 获取今日统计 -------------------
try:
today_stat = ShangjiaRiTongji.query.get(yonghuid=yonghuid, riqi=today)
jinri_paifa_dingdan = today_stat.paifa_dingdan_shu
jinri_paifa_jine = float(today_stat.paifa_jine)
jinri_tuikuan_dingdan = today_stat.tuikuan_dingdan_shu
except ShangjiaRiTongji.DoesNotExist:
today_stat = MerchantDailyStats.query.get(MerchantID=yonghuid, Date=today)
jinri_paifa_dingdan = today_stat.AssignedOrderCount
jinri_paifa_jine = float(today_stat.AssignedAmount)
jinri_tuikuan_dingdan = today_stat.RefundOrderCount
except MerchantDailyStats.DoesNotExist:
jinri_paifa_dingdan = 0
jinri_paifa_jine = 0.00
jinri_tuikuan_dingdan = 0
@@ -1103,14 +1103,14 @@ class ShangJiaXinXiView(APIView):
response_data['jinrituikuan'] = jinri_tuikuan_dingdan # 今日退款数(新增)
response_data['riliushui'] = jinri_paifa_jine # 今日流水(派发总金额)
# ------------------- 4. 从 ShangjiaRiTongji 获取本月统计 -------------------
month_stats = ShangjiaRiTongji.query.filter(
yonghuid=yonghuid,
riqi__gte=this_month_start,
riqi__lte=today
# ------------------- 4. 从 MerchantDailyStats 获取本月统计 -------------------
month_stats = MerchantDailyStats.query.filter(
MerchantID=yonghuid,
Date__gte=this_month_start,
Date__lte=today
).aggregate(
total_paifa_jine=Sum('paifa_jine'),
total_paifa_dingdan=Sum('paifa_dingdan_shu')
total_paifa_jine=Sum('AssignedAmount'),
total_paifa_dingdan=Sum('AssignedOrderCount')
)
yue_paifa_jine = float(month_stats.get('total_paifa_jine') or 0.00)
# yue_paifa_dingdan = month_stats.get('total_paifa_dingdan') or 0 # 如果前端不需要可不加