Files
Django/jituan/services/daily_finance_display.py

94 lines
3.2 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.
"""财务看板:只读 daily_income_stat / daily_payout_stat 表字段,支持按俱乐部 Header 过滤。"""
from datetime import date, timedelta
from django.db.models import Sum
from config.models import DailyIncomeStat, DailyPayoutStat
from jituan.services.club_context import filter_club_char_field
def _income_qs(request):
if request is None:
return DailyIncomeStat.objects.all()
return filter_club_char_field(DailyIncomeStat.objects.all(), request, field='club_id')
def _payout_qs(request):
if request is None:
return DailyPayoutStat.objects.all()
return filter_club_char_field(DailyPayoutStat.objects.all(), request, field='club_id')
def sum_income_stat_for_date(stat_date, request=None):
"""金额 = Sum(total_amount),笔数 = Sum(total_count),与库里 SQL 一致。"""
agg = _income_qs(request).filter(date=stat_date).aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
return float(agg['total_amount'] or 0), int(agg['total_count'] or 0)
def sum_payout_stat_for_date(stat_date, request=None):
agg = _payout_qs(request).filter(date=stat_date).aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
return float(agg['total_amount'] or 0), int(agg['total_count'] or 0)
def today_income_for_dashboard(stat_date=None, request=None):
"""今日收入:只读 daily_income_stat.total_amount / total_count不扫订单。"""
stat_date = stat_date or date.today()
return sum_income_stat_for_date(stat_date, request)
def cumulative_income_payout(request=None):
total_income = float(
_income_qs(request).aggregate(t=Sum('total_amount'))['t'] or 0
)
total_payout = float(
_payout_qs(request).aggregate(t=Sum('total_amount'))['t'] or 0
)
return total_income, total_payout, round(total_income - total_payout, 2)
def daily_stats_for_request(request=None, days=30):
since = date.today() - timedelta(days=days)
income_by_date = {
str(row['date']): {
'income': float(row['total_amount'] or 0),
'income_count': int(row['total_count'] or 0),
}
for row in _income_qs(request).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 _payout_qs(request).filter(date__gte=since).values('date').annotate(
total_amount=Sum('total_amount'),
)
}
daily_stats = []
all_dates = sorted(
set(income_by_date.keys()) | set(payout_by_date.keys()),
reverse=True,
)[:days]
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 daily_stats
def income_count_for_summary_date(stat_date, request=None):
_, count = sum_income_stat_for_date(stat_date, request)
return count