fix: 收入恢复命令修正
This commit is contained in:
@@ -204,24 +204,29 @@ _ORDER_INCOME_STATUSES = [1, 2, 3, 4, 6, 7, 8]
|
||||
_CZ_WECHAT_LEIXING = [1, 2, 3, 4, 5]
|
||||
|
||||
|
||||
def collect_canonical_wechat_income_for_date(stat_date):
|
||||
"""
|
||||
按真实支付时间(UpdateTime)收集当日微信收入,每笔 biz_ref 唯一。
|
||||
返回 [(biz_ref, club_id, amount, kind), ...]
|
||||
def collect_canonical_wechat_income_for_date(stat_date, existing_refs=None):
|
||||
"""
|
||||
收集当日真实微信收入(每笔 biz_ref 全局唯一,不重复计已入账订单)。
|
||||
- 订单:当日创建且已付款,或当日完成微信支付(有微信交易号)
|
||||
- 充值:当日创建且 zhuangtai=3
|
||||
- 不含退款单(Status=5)
|
||||
"""
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.db.models import Q
|
||||
|
||||
from orders.models import Order
|
||||
from products.models import Czjilu
|
||||
|
||||
day_start = datetime.combine(stat_date, datetime.min.time())
|
||||
day_end = day_start + timedelta(days=1)
|
||||
skip_refs = existing_refs or set()
|
||||
seen = {}
|
||||
items = []
|
||||
|
||||
def _add(ref, club_id, amount, kind):
|
||||
ref = (ref or '').strip()
|
||||
if not ref or ref in seen:
|
||||
if not ref or ref in seen or ref in skip_refs:
|
||||
return
|
||||
jine = Decimal(str(amount or 0))
|
||||
if jine <= 0:
|
||||
@@ -230,16 +235,25 @@ def collect_canonical_wechat_income_for_date(stat_date):
|
||||
seen[ref] = True
|
||||
items.append((ref, cid, jine, kind))
|
||||
|
||||
for od in Order.query.filter(
|
||||
UpdateTime__gte=day_start,
|
||||
UpdateTime__lt=day_end,
|
||||
order_qs = Order.query.filter(
|
||||
Status__in=_ORDER_INCOME_STATUSES,
|
||||
):
|
||||
).filter(
|
||||
Q(CreateTime__gte=day_start, CreateTime__lt=day_end)
|
||||
| Q(
|
||||
UpdateTime__gte=day_start,
|
||||
UpdateTime__lt=day_end,
|
||||
WechatTransactionID__isnull=False,
|
||||
),
|
||||
)
|
||||
for od in order_qs:
|
||||
txn = (getattr(od, 'WechatTransactionID', None) or '').strip()
|
||||
if not txn:
|
||||
continue
|
||||
_add(f'order:{od.OrderID}', getattr(od, 'ClubID', None), od.Amount, 'order')
|
||||
|
||||
for cz in Czjilu.query.filter(
|
||||
UpdateTime__gte=day_start,
|
||||
UpdateTime__lt=day_end,
|
||||
CreateTime__gte=day_start,
|
||||
CreateTime__lt=day_end,
|
||||
zhuangtai=3,
|
||||
leixing__in=_CZ_WECHAT_LEIXING,
|
||||
):
|
||||
@@ -248,6 +262,53 @@ def collect_canonical_wechat_income_for_date(stat_date):
|
||||
return items
|
||||
|
||||
|
||||
def _existing_refs_outside_date(stat_date):
|
||||
"""该日之外已入账的 biz_ref(删当日错误日志后仍保留的)。"""
|
||||
try:
|
||||
return set(
|
||||
PlatformIncomeLog.objects.exclude(
|
||||
CreateTime__date=stat_date,
|
||||
).values_list('biz_ref', flat=True)
|
||||
)
|
||||
except _PLATFORM_LOG_ERRORS:
|
||||
return set()
|
||||
|
||||
|
||||
def rebuild_all_daily_income_from_logs():
|
||||
"""按 platform_income_log 全量重写 daily_income_stat(日志为唯一准绳)。"""
|
||||
from django.db.models.functions import TruncDate
|
||||
|
||||
try:
|
||||
grouped = (
|
||||
PlatformIncomeLog.objects.annotate(log_date=TruncDate('CreateTime'))
|
||||
.values('log_date', 'club_id')
|
||||
.annotate(total_amount=Sum('amount'), total_count=Count('id'))
|
||||
)
|
||||
except _PLATFORM_LOG_ERRORS as exc:
|
||||
logger.error('platform_income_log 不可用: %s', exc)
|
||||
return 0
|
||||
|
||||
with transaction.atomic():
|
||||
DailyIncomeStat.objects.all().delete()
|
||||
n = 0
|
||||
for row in grouped:
|
||||
d = row['log_date']
|
||||
if not d:
|
||||
continue
|
||||
cid = normalize_szjilu_club_id(row['club_id'])
|
||||
DailyIncomeStat.objects.create(
|
||||
date=d,
|
||||
club_id=cid,
|
||||
year=d.year,
|
||||
month=d.month,
|
||||
day=d.day,
|
||||
total_amount=row['total_amount'] or _ZERO,
|
||||
total_count=int(row['total_count'] or 0),
|
||||
)
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
def recover_income_stats_for_date(stat_date, dry_run=True):
|
||||
"""
|
||||
撤销 repair_wechat_income 造成的重复记账:
|
||||
@@ -283,7 +344,8 @@ def recover_income_stats_for_date(stat_date, dry_run=True):
|
||||
except _PLATFORM_LOG_ERRORS:
|
||||
pass
|
||||
|
||||
items = collect_canonical_wechat_income_for_date(stat_date)
|
||||
existing_refs = _existing_refs_outside_date(stat_date)
|
||||
items = collect_canonical_wechat_income_for_date(stat_date, existing_refs=existing_refs)
|
||||
rebuild_amt = sum((x[2] for x in items), _ZERO)
|
||||
rebuild_cnt = len(items)
|
||||
|
||||
@@ -316,6 +378,9 @@ def recover_income_stats_for_date(stat_date, dry_run=True):
|
||||
|
||||
DailyIncomeStat.objects.filter(date=stat_date).delete()
|
||||
|
||||
existing_refs = _existing_refs_outside_date(stat_date)
|
||||
items = collect_canonical_wechat_income_for_date(stat_date, existing_refs=existing_refs)
|
||||
|
||||
for ref, cid, jine, _kind in items:
|
||||
log = PlatformIncomeLog.objects.create(
|
||||
biz_ref=ref,
|
||||
|
||||
Reference in New Issue
Block a user