fix: 支付入账降级 + 财务全平台汇总

This commit is contained in:
XingQue
2026-06-24 20:58:28 +08:00
parent a693e35177
commit 0827da594c
4 changed files with 163 additions and 56 deletions

View File

@@ -87,13 +87,29 @@ def build_caiwu_payload(request):
income_qs = _daily_income_qs(request)
payout_qs = _daily_payout_qs(request)
today_income = income_qs.filter(date=today).first()
today_income_amount = float(today_income.total_amount) if today_income else 0.00
today_income_count = today_income.total_count if today_income else 0
today_payout = payout_qs.filter(date=today).first()
today_payout_amount = float(today_payout.total_amount) if today_payout else 0.00
today_payout_count = today_payout.total_count if today_payout else 0
scope = resolve_club_scope(request)
today_income_qs = income_qs.filter(date=today)
today_payout_qs = payout_qs.filter(date=today)
if scope == DATA_SCOPE_ALL:
inc_agg = today_income_qs.aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
today_income_amount = float(inc_agg['total_amount'] or 0.00)
today_income_count = int(inc_agg['total_count'] or 0)
pay_agg = today_payout_qs.aggregate(
total_amount=Sum('total_amount'),
total_count=Sum('total_count'),
)
today_payout_amount = float(pay_agg['total_amount'] or 0.00)
today_payout_count = int(pay_agg['total_count'] or 0)
else:
today_income = today_income_qs.first()
today_income_amount = float(today_income.total_amount) if today_income else 0.00
today_income_count = today_income.total_count if today_income else 0
today_payout = today_payout_qs.first()
today_payout_amount = float(today_payout.total_amount) if today_payout else 0.00
today_payout_count = today_payout.total_count if today_payout else 0
today_orders = order_qs.filter(
CreateTime__gte=today_start,
@@ -150,20 +166,54 @@ def build_caiwu_payload(request):
platform_profit = round(total_income - total_payout, 2)
daily_stats = []
income_list = income_qs.order_by('-date')[:30]
payout_dict = {
str(p.date): float(p.total_amount)
for p in payout_qs.filter(date__gte=today - timedelta(days=30))
}
for inc in income_list:
d = str(inc.date)
daily_stats.append({
'date': d,
'income': float(inc.total_amount),
'income_count': inc.total_count,
'payout': payout_dict.get(d, 0.00),
'profit': round(float(inc.total_amount) - payout_dict.get(d, 0.00), 2),
})
since = today - timedelta(days=30)
if scope == DATA_SCOPE_ALL:
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.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.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),
})
else:
income_list = income_qs.filter(date__gte=since).order_by('-date')[:30]
payout_dict = {
str(p.date): float(p.total_amount)
for p in payout_qs.filter(date__gte=since)
}
for inc in income_list:
d = str(inc.date)
payout_amt = payout_dict.get(d, 0.00)
daily_stats.append({
'date': d,
'income': float(inc.total_amount),
'income_count': inc.total_count,
'payout': payout_amt,
'profit': round(float(inc.total_amount) - payout_amt, 2),
})
return {
'club_id': club_id,

View File

@@ -3,6 +3,7 @@ import logging
from decimal import Decimal
from django.db import IntegrityError, transaction
from django.db.utils import OperationalError, ProgrammingError
from config.models import PlatformIncomeLog, Szjilu
from jituan.constants import CLUB_ID_DEFAULT
@@ -18,6 +19,8 @@ _SZJILU_DEFAULTS = {
'DailyFlow': _ZERO,
}
_PLATFORM_LOG_ERRORS = (ProgrammingError, OperationalError)
def normalize_szjilu_club_id(club_id):
return (club_id or '').strip() or CLUB_ID_DEFAULT
@@ -43,17 +46,27 @@ def apply_szjilu_income(amount, club_id=None):
szjilu.save()
def _apply_income_stats(amount, club_id):
"""写入 daily_income_stat + szjilu核心统计必须成功"""
from orders.utils import update_daily_income
cid = normalize_szjilu_club_id(club_id)
jine = Decimal(str(amount))
update_daily_income(jine, cid)
apply_szjilu_income(jine, cid)
def record_wechat_income_once(amount, club_id=None, biz_ref=None):
"""
微信入账:同一 biz_ref 只记一次 daily_income_stat + szjilu。
返回 True=本次新入账False=已记过(重复回调/重复代码路径)。
返回 True=本次新入账False=已记过(重复回调)。
若 platform_income_log 表不可用,仍记入收入(与改造前一致,不能因幂等表故障丢统计)。
"""
ref = (biz_ref or '').strip()
if not ref:
raise ValueError('biz_ref 不能为空')
cid = normalize_szjilu_club_id(club_id)
jine = Decimal(str(amount))
from orders.utils import update_daily_income
try:
with transaction.atomic():
@@ -65,12 +78,28 @@ def record_wechat_income_once(amount, club_id=None, biz_ref=None):
except IntegrityError:
logger.info('平台入账已存在,跳过重复记账 biz_ref=%s', ref)
return False
except _PLATFORM_LOG_ERRORS as exc:
logger.warning(
'platform_income_log 不可用(%s),跳过幂等直接记入收入 biz_ref=%s',
exc, ref,
)
_apply_income_stats(jine, cid)
return True
except Exception as exc:
logger.error(
'platform_income_log 写入异常,仍记入收入 biz_ref=%s err=%s',
ref, exc, exc_info=True,
)
_apply_income_stats(jine, cid)
return True
try:
update_daily_income(jine, cid)
apply_szjilu_income(jine, cid)
_apply_income_stats(jine, cid)
except Exception:
PlatformIncomeLog.objects.filter(biz_ref=ref).delete()
try:
PlatformIncomeLog.objects.filter(biz_ref=ref).delete()
except Exception:
pass
raise
logger.info('平台入账记账成功 biz_ref=%s club=%s amount=%s', ref, cid, jine)
return True