Files
Django/jituan/services/caiwu_stats.py

201 lines
7.7 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.
"""俱乐部维度财务统计(供 /jituan/houtai/caiwu旧 /houtai/caiwu 不变)。"""
from datetime import date, datetime, timedelta
from django.db.models import Sum
from jituan.services.club_context import (
filter_club_char_field,
filter_queryset_by_club,
resolve_club_id_from_request,
resolve_club_scope,
)
from jituan.constants import DATA_SCOPE_ALL
from config.models import DailyIncomeStat, DailyPayoutStat
from orders.models import Order
from products.models import Czjilu, Huiyuangoumai
from users.models import UserDashou, UserGuanshi, UserShangjia, UserZuzhang
def _role_profile_qs(profile_model, request):
"""按俱乐部过滤角色扩展表(通过 user.ClubID"""
qs = profile_model.query.all()
if resolve_club_scope(request) == DATA_SCOPE_ALL:
return qs
return qs.filter(user__ClubID=resolve_club_id_from_request(request))
def _sum_role_balance(profile_model, balance_field, request):
return float(
_role_profile_qs(profile_model, request).aggregate(total=Sum(balance_field))['total'] or 0.00
)
def _order_qs(request):
return filter_queryset_by_club(Order.query.all(), request, club_field='ClubID')
def _czjilu_qs(request):
return filter_club_char_field(Czjilu.query.all(), request, field='club_id')
def _huiyuangoumai_qs(request):
return filter_club_char_field(Huiyuangoumai.query.all(), request, field='club_id')
def _daily_income_qs(request):
return filter_club_char_field(DailyIncomeStat.query.all(), request, field='club_id')
def _daily_payout_qs(request):
return filter_club_char_field(DailyPayoutStat.query.all(), request, field='club_id')
def build_caiwu_payload(request):
"""与 CaiwuView 返回结构一致;收入/支出只读 daily_income_stat、daily_payout_stat。"""
today = date.today()
today_start = datetime.combine(today, datetime.min.time())
today_end = today_start + timedelta(days=1)
club_id = resolve_club_id_from_request(request)
order_qs = _order_qs(request)
cz_qs = _czjilu_qs(request)
hy_qs = _huiyuangoumai_qs(request)
payout_qs = _daily_payout_qs(request)
scope = resolve_club_scope(request)
# 四个板子:全平台合计(与 /houtai/caiwu 一致,读 date 字段)
today_inc = DailyIncomeStat.query.filter(date=today).aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
today_income_amount = float(today_inc['total_amount'] or 0.00)
today_income_count = int(today_inc['total_count'] or 0)
today_pay = DailyPayoutStat.query.filter(date=today).aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
today_payout_amount = float(today_pay['total_amount'] or 0.00)
today_payout_count = int(today_pay['total_count'] or 0)
today_orders = order_qs.filter(
CreateTime__gte=today_start,
CreateTime__lt=today_end,
Status__in=[1, 2, 3, 4, 5, 6, 7, 8],
)
today_order_count = today_orders.count()
today_order_amount = float(today_orders.aggregate(total=Sum('Amount'))['total'] or 0.00)
today_completed = order_qs.filter(
CreateTime__gte=today_start, CreateTime__lt=today_end, Status=3,
)
today_completed_count = today_completed.count()
today_completed_amount = float(today_completed.aggregate(total=Sum('Amount'))['total'] or 0.00)
today_tuikuan = order_qs.filter(
CreateTime__gte=today_start, CreateTime__lt=today_end, Status=5,
)
today_tuikuan_count = today_tuikuan.count()
today_tuikuan_amount = float(today_tuikuan.aggregate(total=Sum('Amount'))['total'] or 0.00)
today_chongzhi = cz_qs.filter(
CreateTime__gte=today_start, CreateTime__lt=today_end, leixing=1, zhuangtai=3,
)
today_chongzhi_count = today_chongzhi.count()
today_chongzhi_amount = float(today_chongzhi.aggregate(total=Sum('jine'))['total'] or 0.00)
new_huiyuan_user_ids = hy_qs.filter(
CreateTime__gte=today_start, CreateTime__lt=today_end,
).values_list('yonghu_id', flat=True).distinct()
today_new_huiyuan = len(list(new_huiyuan_user_ids))
today_new_huiyuan_amount = 0.0
if new_huiyuan_user_ids:
amount_sum = cz_qs.filter(
CreateTime__gte=today_start,
CreateTime__lt=today_end,
yonghuid__in=new_huiyuan_user_ids,
leixing=1,
zhuangtai=3,
).aggregate(total=Sum('jine'))
today_new_huiyuan_amount = float(amount_sum['total'] or 0.0)
all_guanshi_yue = _sum_role_balance(UserGuanshi, 'yue', request)
all_dashou_yue = _sum_role_balance(UserDashou, 'yue', request)
all_zuzhang_yue = _sum_role_balance(UserZuzhang, 'ketixian_jine', request)
all_shangjia_yue = _sum_role_balance(UserShangjia, 'yue', request)
total_income = float(
DailyIncomeStat.query.aggregate(total=Sum('total_amount'))['total'] or 0.00
)
total_payout = float(
DailyPayoutStat.query.aggregate(total=Sum('total_amount'))['total'] or 0.00
)
scoped_income_qs = _daily_income_qs(request)
scoped_payout_qs = _daily_payout_qs(request)
scoped_total_income = float(scoped_income_qs.aggregate(total=Sum('total_amount'))['total'] or 0.00)
scoped_total_payout = float(scoped_payout_qs.aggregate(total=Sum('total_amount'))['total'] or 0.00)
platform_profit = round(scoped_total_income - scoped_total_payout, 2)
daily_stats = []
since = today - timedelta(days=30)
income_by_date = {
str(row['date']): {
'income': float(row['total_amount'] or 0),
'income_count': int(row['total_count'] or 0),
}
for row in DailyIncomeStat.query.filter(date__gte=since).values('date').annotate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
}
payout_by_date = {
str(row['date']): float(row['total_amount'] or 0)
for row in DailyPayoutStat.query.filter(date__gte=since).values('date').annotate(
total_amount=Sum('total_amount'),
)
}
all_dates = sorted(
set(income_by_date.keys()) | set(payout_by_date.keys()),
reverse=True,
)[:30]
for d in all_dates:
inc = income_by_date.get(d, {'income': 0.0, 'income_count': 0})
payout_amt = payout_by_date.get(d, 0.00)
daily_stats.append({
'date': d,
'income': inc['income'],
'income_count': inc['income_count'],
'payout': payout_amt,
'profit': round(inc['income'] - payout_amt, 2),
})
return {
'club_id': club_id,
'scope': resolve_club_scope(request),
'today_income': round(today_income_amount, 2),
'today_income_count': today_income_count,
'today_payout': round(today_payout_amount, 2),
'today_payout_count': today_payout_count,
'today_order_count': today_order_count,
'today_order_amount': round(today_order_amount, 2),
'today_completed_count': today_completed_count,
'today_completed_amount': round(today_completed_amount, 2),
'today_tuikuan_count': today_tuikuan_count,
'today_tuikuan_amount': round(today_tuikuan_amount, 2),
'today_chongzhi_count': today_chongzhi_count,
'today_chongzhi_amount': round(today_chongzhi_amount, 2),
'today_new_huiyuan': today_new_huiyuan,
'today_new_huiyuan_amount': round(today_new_huiyuan_amount, 2),
'all_guanshi_yue': round(all_guanshi_yue, 2),
'all_dashou_yue': round(all_dashou_yue, 2),
'all_zuzhang_yue': round(all_zuzhang_yue, 2),
'all_shangjia_yue': round(all_shangjia_yue, 2),
'total_income': round(total_income, 2),
'total_payout': round(total_payout, 2),
'platform_profit': platform_profit,
'daily_stats': daily_stats,
}