fix: separate penalty czjilu from merchant recharge and correct finance stats
This commit is contained in:
@@ -20,6 +20,12 @@ def _club_id_from_user_uid(uid):
|
||||
return None
|
||||
|
||||
|
||||
def penalty_cz_club_id(fadan):
|
||||
"""罚款支付 czjilu.club_id:与罚单归属一致(申请人俱乐部)。"""
|
||||
cid = (getattr(fadan, 'ClubID', None) or '').strip()
|
||||
return cid or CLUB_ID_DEFAULT
|
||||
|
||||
|
||||
def resolve_penalty_club_id(
|
||||
order=None,
|
||||
penalized_user_id=None,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"""财务子模块统计(订单/会员/其他充值),供 /jituan/houtai/*;旧 /houtai/* 不变。"""
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db.models import Count, Q, Sum
|
||||
from django.db.models import Case, Count, DecimalField, Q, Sum, Value, When
|
||||
from django.db.models.functions import TruncDate, TruncMonth, TruncYear
|
||||
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
@@ -13,6 +14,7 @@ from jituan.services.club_context import (
|
||||
)
|
||||
from jituan.services.club_penalty import filter_gsfenhong_qs, filter_penalty_qs
|
||||
from orders.models import Order, Penalty
|
||||
from products.czjilu_types import CZJILU_LEIXING_SHANGJIA, exclude_penalty_from_cz_qs
|
||||
from products.models import Czjilu, Gsfenhong, Huiyuan, ShangpinLeixing
|
||||
from rank.models import Bankuai
|
||||
|
||||
@@ -77,6 +79,57 @@ def _summary_date_filter(granularity, summary_q, field_prefix='CreateTime'):
|
||||
return {f'{field_prefix}__year': summary_q.year}
|
||||
|
||||
|
||||
def _penalty_trunc_func(granularity):
|
||||
if granularity == 'day':
|
||||
return TruncDate('UpdateTime')
|
||||
if granularity == 'month':
|
||||
return TruncMonth('UpdateTime')
|
||||
return TruncYear('UpdateTime')
|
||||
|
||||
|
||||
def _penalty_fenhong_aggregates():
|
||||
"""罚款分红只统计已入账(BonusCredited),与 process_fadan_fenhong 一致。"""
|
||||
zero = Value(Decimal('0.00'), output_field=DecimalField(max_digits=12, decimal_places=2))
|
||||
return {
|
||||
'fenhong_amount': Sum(
|
||||
Case(
|
||||
When(BonusCredited=True, then='ApplicantBonusAmount'),
|
||||
default=zero,
|
||||
output_field=DecimalField(max_digits=12, decimal_places=2),
|
||||
)
|
||||
),
|
||||
'fenhong_count': Count(
|
||||
'id',
|
||||
filter=Q(BonusCredited=True, ApplicantBonusAmount__gt=0),
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _czjilu_finance_qs(request, start_dt, end_dt, cz_types):
|
||||
"""充值财务 czjilu:已支付;type4 排除罚款误标。"""
|
||||
qs = filter_queryset_by_club(
|
||||
Czjilu.query.filter(
|
||||
CreateTime__gte=start_dt,
|
||||
CreateTime__lt=end_dt,
|
||||
leixing__in=cz_types,
|
||||
zhuangtai=3,
|
||||
),
|
||||
request,
|
||||
)
|
||||
if CZJILU_LEIXING_SHANGJIA in cz_types:
|
||||
qs = exclude_penalty_from_cz_qs(qs)
|
||||
return qs
|
||||
|
||||
|
||||
def _czjilu_summary_qs(request, lx, granularity, summary_q):
|
||||
filter_kwargs = {'leixing': lx, 'zhuangtai': 3}
|
||||
filter_kwargs.update(_summary_date_filter(granularity, summary_q))
|
||||
qs = filter_queryset_by_club(Czjilu.query.filter(**filter_kwargs), request)
|
||||
if lx == CZJILU_LEIXING_SHANGJIA:
|
||||
qs = exclude_penalty_from_cz_qs(qs)
|
||||
return qs
|
||||
|
||||
|
||||
def build_order_types_payload():
|
||||
types = ShangpinLeixing.query.filter(shenhezhuangtai=1).values('id', 'jieshao')
|
||||
return list(types)
|
||||
@@ -209,15 +262,9 @@ def build_chongzhi_finance_payload(request, granularity, year, month, types=None
|
||||
|
||||
cz_types = [t for t in types if t in [2, 3, 4, 5]]
|
||||
if cz_types:
|
||||
cz_qs = filter_queryset_by_club(
|
||||
Czjilu.query.filter(
|
||||
CreateTime__gte=start_dt,
|
||||
CreateTime__lt=end_dt,
|
||||
leixing__in=cz_types,
|
||||
zhuangtai=3,
|
||||
),
|
||||
request,
|
||||
).annotate(period=trunc_func).values('period', 'leixing').annotate(
|
||||
cz_qs = _czjilu_finance_qs(request, start_dt, end_dt, cz_types).annotate(
|
||||
period=trunc_func,
|
||||
).values('period', 'leixing').annotate(
|
||||
total_count=Count('id'),
|
||||
total_amount=Sum('jine'),
|
||||
).order_by('period', 'leixing')
|
||||
@@ -242,14 +289,18 @@ def build_chongzhi_finance_payload(request, granularity, year, month, types=None
|
||||
}
|
||||
|
||||
if 6 in types:
|
||||
penalty_trunc = _penalty_trunc_func(granularity)
|
||||
penalty_qs = filter_penalty_qs(
|
||||
Penalty.query.filter(CreateTime__gte=start_dt, CreateTime__lt=end_dt, Status=2),
|
||||
Penalty.query.filter(
|
||||
UpdateTime__gte=start_dt,
|
||||
UpdateTime__lt=end_dt,
|
||||
Status=2,
|
||||
),
|
||||
request,
|
||||
).annotate(period=trunc_func).values('period').annotate(
|
||||
).annotate(period=penalty_trunc).values('period').annotate(
|
||||
penalty_count=Count('id'),
|
||||
penalty_amount=Sum('FineAmount'),
|
||||
fenhong_amount=Sum('ApplicantBonusAmount'),
|
||||
fenhong_count=Count('id', filter=Q(ApplicantBonusAmount__gt=0)),
|
||||
**_penalty_fenhong_aggregates(),
|
||||
).order_by('period')
|
||||
|
||||
for item in penalty_qs:
|
||||
@@ -279,9 +330,7 @@ def build_chongzhi_finance_payload(request, granularity, year, month, types=None
|
||||
summary_result = {'by_type': {}, 'total_count': 0, 'total_amount': 0.0, 'total_profit': 0.0}
|
||||
|
||||
for lx in cz_types:
|
||||
filter_kwargs = {'leixing': lx, 'zhuangtai': 3}
|
||||
filter_kwargs.update(_summary_date_filter(granularity, summary_q))
|
||||
agg = filter_queryset_by_club(Czjilu.query.filter(**filter_kwargs), request).aggregate(
|
||||
agg = _czjilu_summary_qs(request, lx, granularity, summary_q).aggregate(
|
||||
count=Count('id'), amount=Sum('jine'),
|
||||
)
|
||||
count = agg['count'] or 0
|
||||
@@ -300,12 +349,11 @@ def build_chongzhi_finance_payload(request, granularity, year, month, types=None
|
||||
|
||||
if 6 in types:
|
||||
penalty_filter = {'Status': 2}
|
||||
penalty_filter.update(_summary_date_filter(granularity, summary_q))
|
||||
penalty_filter.update(_summary_date_filter(granularity, summary_q, field_prefix='UpdateTime'))
|
||||
agg = filter_penalty_qs(Penalty.query.filter(**penalty_filter), request).aggregate(
|
||||
count=Count('id'),
|
||||
amount=Sum('FineAmount'),
|
||||
fenhong_amount=Sum('ApplicantBonusAmount'),
|
||||
fenhong_count=Count('id', filter=Q(ApplicantBonusAmount__gt=0)),
|
||||
**_penalty_fenhong_aggregates(),
|
||||
)
|
||||
penalty_count = agg['count'] or 0
|
||||
penalty_amount = float(agg['amount'] or 0)
|
||||
|
||||
@@ -309,8 +309,8 @@ def sync_szjilu_income_from_logs():
|
||||
|
||||
# 订单已付款且非退款(repair 错误地把 Status=5 退款单也计入了收入)
|
||||
_ORDER_INCOME_STATUSES = [1, 2, 3, 4, 6, 7, 8]
|
||||
# 微信充值类 czjilu:会员/押金/积分/商家/罚单/考核
|
||||
_CZ_WECHAT_LEIXING = [1, 2, 3, 4, 5]
|
||||
# 微信充值类 czjilu:会员/押金/积分/商家/考核/罚款
|
||||
_CZ_WECHAT_LEIXING = [1, 2, 3, 4, 5, 6]
|
||||
|
||||
|
||||
def collect_canonical_wechat_income_for_date(stat_date, existing_refs=None):
|
||||
@@ -701,7 +701,7 @@ def reset_all_daily_szjilu():
|
||||
|
||||
# 合法微信支付收入(不含退款 Status=5)
|
||||
_LEGIT_ORDER_STATUSES = [1, 2, 3, 4, 6, 7, 8]
|
||||
_LEGIT_CZ_LEIXING = [1, 2, 3, 4, 5]
|
||||
_LEGIT_CZ_LEIXING = [1, 2, 3, 4, 5, 6]
|
||||
|
||||
|
||||
def collect_legitimate_wechat_payments(since_year, until_year):
|
||||
|
||||
Reference in New Issue
Block a user