Files
along_django/yonghu/ranking_tasks.py

280 lines
9.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# yonghu/ranking_tasks.py
"""
排行榜数据转移任务 - 生产环境专用
在清空前将数据转移到排行榜表
"""
from celery import shared_task
from django.db import transaction
from django.utils import timezone
from datetime import datetime, timedelta
import logging
from decimal import Decimal
from yonghu.models import (
UserMain, UserDashou, UserShangjia, UserGuanshi, UserBoss,
RankingRecord
)
logger = logging.getLogger(__name__)
def get_user_nicheng(user, shenfen):
"""
获取用户昵称
规则打手用打手nicheng其他用老板nickname
"""
try:
if shenfen == 2: # 打手
dashou_profile = getattr(user, 'dashou_profile', None)
if dashou_profile and dashou_profile.nicheng:
return dashou_profile.nicheng
else: # 管事或商家
boss_profile = getattr(user, 'boss_profile', None)
if boss_profile and boss_profile.nickname:
return boss_profile.nickname
# 默认返回用户ID
return f"用户{user.yonghuid}"
except Exception:
return f"用户{user.yonghuid}"
@shared_task
def zhuanyi_ribang():
"""
转移日榜数据 - 每天23:55执行
在清零前将今日数据转移到排行榜表
"""
try:
# 统计日期(今天)
today = timezone.now().date()
logger.info(f"开始转移日榜数据,日期: {today}")
records_to_create = []
# 1. 转移打手日榜(今日收益 > 0
dashou_list = UserDashou.objects.filter(
jinrishouyi__gt=0 # 只转移收益大于0的
).select_related('user').order_by('-jinrishouyi')
for i, dashou in enumerate(dashou_list, start=1):
if i > 100: # 最多100条
break
user = dashou.user
record = RankingRecord(
zhouqi=1, # 日榜
tongji_date=today,
shenfen=2, # 打手
yonghuid=user.yonghuid,
paiming=i,
zhizhi=dashou.jinrishouyi,
nicheng=get_user_nicheng(user, 2),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 2. 转移商家日榜(今日流水 > 0
shangjia_list = UserShangjia.objects.filter(
jinriliushui__gt=0 # 只转移流水大于0的
).select_related('user').order_by('-jinriliushui')
for i, shangjia in enumerate(shangjia_list, start=1):
if i > 100: # 最多100条
break
user = shangjia.user
record = RankingRecord(
zhouqi=1,
tongji_date=today,
shenfen=4, # 商家
yonghuid=user.yonghuid,
paiming=i,
zhizhi=shangjia.jinriliushui,
nicheng=get_user_nicheng(user, 4),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 3. 转移管事日榜(今日充值人数 > 0
guanshi_list = UserGuanshi.objects.filter(
jinrichongzhi__gt=0 # 只转移充值人数大于0的
).select_related('user').order_by('-jinrichongzhi')
for i, guanshi in enumerate(guanshi_list, start=1):
if i > 100: # 最多100条
break
user = guanshi.user
record = RankingRecord(
zhouqi=1,
tongji_date=today,
shenfen=3, # 管事
yonghuid=user.yonghuid,
paiming=i,
zhizhi=Decimal(guanshi.jinrichongzhi),
nicheng=get_user_nicheng(user, 3),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 批量保存
if records_to_create:
with transaction.atomic():
RankingRecord.objects.bulk_create(records_to_create)
logger.info(f"日榜数据转移完成,保存{len(records_to_create)}条记录")
result = {
'success': True,
'date': today.strftime('%Y-%m-%d'),
'total_count': len(records_to_create),
}
return result
except Exception as e:
logger.error(f"日榜数据转移失败: {str(e)}", exc_info=True)
raise
@shared_task
def zhuanyi_yuebang():
"""
转移月榜数据 - 每月最后一天23:50执行
在清零前将本月数据转移到排行榜表
"""
try:
# 🔥 获取当前时间
now = timezone.now()
today = now.date()
# 🔥 判断今天是否是当月的最后一天
# 方法:计算明天的日期,如果明天的月份和今天不同,那么今天就是最后一天
tomorrow = today + timedelta(days=1)
if tomorrow.month == today.month:
# 今天不是最后一天,直接返回
logger.info(f"今天不是当月最后一天({today}),跳过月榜转移")
return {
'success': True,
'message': f'今天不是当月最后一天,跳过执行',
'is_last_day': False,
'today': today.strftime('%Y-%m-%d'),
}
logger.info(f"今天是当月最后一天({today}),开始转移月榜数据")
# 🔥 统计日期为当月第一天如2024-01-01
tongji_date = datetime(today.year, today.month, 1).date()
records_to_create = []
# 1. 转移打手月榜(今月收益 > 0
dashou_list = UserDashou.objects.filter(
jinyueshouyi__gt=0 # 只转移收益大于0的
).select_related('user').order_by('-jinyueshouyi')
for i, dashou in enumerate(dashou_list, start=1):
if i > 100: # 最多100条
break
user = dashou.user
record = RankingRecord(
zhouqi=2, # 月榜
tongji_date=tongji_date,
shenfen=2, # 打手
yonghuid=user.yonghuid,
paiming=i,
zhizhi=dashou.jinyueshouyi,
nicheng=get_user_nicheng(user, 2),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 2. 转移商家月榜(今月流水 > 0
shangjia_list = UserShangjia.objects.filter(
jinyueliushui__gt=0 # 只转移流水大于0的
).select_related('user').order_by('-jinyueliushui')
for i, shangjia in enumerate(shangjia_list, start=1):
if i > 100: # 最多100条
break
user = shangjia.user
record = RankingRecord(
zhouqi=2,
tongji_date=tongji_date,
shenfen=4, # 商家
yonghuid=user.yonghuid,
paiming=i,
zhizhi=shangjia.jinyueliushui,
nicheng=get_user_nicheng(user, 4),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 3. 转移管事月榜(今月充值人数 > 0
guanshi_list = UserGuanshi.objects.filter(
jinyuechongzhi__gt=0 # 只转移充值人数大于0的
).select_related('user').order_by('-jinyuechongzhi')
for i, guanshi in enumerate(guanshi_list, start=1):
if i > 100: # 最多100条
break
user = guanshi.user
record = RankingRecord(
zhouqi=2,
tongji_date=tongji_date,
shenfen=3, # 管事
yonghuid=user.yonghuid,
paiming=i,
zhizhi=Decimal(guanshi.jinyuechongzhi),
nicheng=get_user_nicheng(user, 3),
avatar=user.avatar or ''
)
records_to_create.append(record)
# 批量保存
if records_to_create:
with transaction.atomic():
RankingRecord.objects.bulk_create(records_to_create)
logger.info(f"月榜数据转移完成,保存{len(records_to_create)}条记录")
result = {
'success': True,
'month': tongji_date.strftime('%Y-%m'),
'total_count': len(records_to_create),
'is_last_day': True,
'today': today.strftime('%Y-%m-%d'),
}
return result
except Exception as e:
logger.error(f"月榜数据转移失败: {str(e)}", exc_info=True)
raise
@shared_task
def qingli_jiulishuju():
"""
清理旧历史数据 - 每月1号凌晨1点执行
清理3个月前的排行榜数据保留最近3个月的数据
"""
try:
# 计算3个月前的日期
three_months_ago = timezone.now().date() - timedelta(days=90)
# 删除旧数据
deleted_count, _ = RankingRecord.objects.filter(
tongji_date__lt=three_months_ago
).delete()
logger.info(f"清理旧历史数据完成,删除{deleted_count}条记录")
return {
'success': True,
'deleted_count': deleted_count,
'before_date': three_months_ago.strftime('%Y-%m-%d')
}
except Exception as e:
logger.error(f"清理旧历史数据失败: {str(e)}")
raise