fix: 收入恢复命令修正

This commit is contained in:
XingQue
2026-06-24 21:21:54 +08:00
parent 600188a99a
commit 3b7c539a56
2 changed files with 124 additions and 52 deletions

View File

@@ -1,38 +1,39 @@
"""
恢复被 repair_wechat_income 搞乱的收入统计。
repair 会对已入账订单重复加钱200 变 900 就是这个)。
本命令:删当日错误日志 → 按真实微信支付重建 → 重算日统计和 szjilu。
repair 会对已入账订单重复加钱200 变 900
本命令:删当日错误日志 → 按真实微信支付重建 → 扣回 szjilu 多记部分
先不加 --yes 可预览重建后金额。
用法:
1. 先预览python manage.py recover_wechat_income_stats
2. 看「重建后」金额是否对(应接近真实收入,如 200 左右)
3. 确认后python manage.py recover_wechat_income_stats --yes
4. 若多日错乱python manage.py recover_wechat_income_stats --days 7 --yes
5. 最后全量对齐日统计表python manage.py recover_wechat_income_stats --yes --rebuild-all-daily
"""
from datetime import date, timedelta
from django.core.management.base import BaseCommand
from django.db.models import Sum
from jituan.services.szjilu_accounting import recover_income_stats_for_date
from config.models import DailyIncomeStat
from jituan.services.szjilu_accounting import (
rebuild_all_daily_income_from_logs,
recover_income_stats_for_date,
)
class Command(BaseCommand):
help = '恢复 repair_wechat_income 造成的重复记账(先预览,再加 --yes 执行)'
help = '恢复 repair_wechat_income 重复记账(先预览,--yes 执行)'
def add_arguments(self, parser):
parser.add_argument('--date', type=str, default='', help='日期 YYYY-MM-DD默认今天')
parser.add_argument('--days', type=int, default=1, help='向前恢复几天')
parser.add_argument('--yes', action='store_true', help='确认执行')
parser.add_argument(
'--date',
type=str,
default='',
help='恢复日期 YYYY-MM-DD默认今天',
)
parser.add_argument(
'--days',
type=int,
default=1,
help='从指定日期起向前恢复几天,默认 1',
)
parser.add_argument(
'--yes',
'--rebuild-all-daily',
action='store_true',
help='确认执行(不加则仅预览,不改数据库',
help='恢复后按 platform_income_log 全量重写 daily_income_stat纠正累计总收入',
)
def handle(self, *args, **options):
@@ -46,40 +47,46 @@ class Command(BaseCommand):
if dry_run:
self.stdout.write(self.style.WARNING(
'【预览模式】未改数据库。确认金额无误后加 --yes 执行\n'
'【预览】未改数据库。下面「重建后」应是正确金额\n'
))
else:
self.stdout.write(self.style.WARNING('【执行模式】正在恢复数据...\n'))
self.stdout.write(self.style.WARNING('【执行】正在恢复...\n'))
for i in range(days):
d = start_day + timedelta(days=i)
r = recover_income_stats_for_date(d, dry_run=dry_run)
self.stdout.write(f"=== {r['date']} ===")
self.stdout.write(f'=== {r["date"]} ===')
self.stdout.write(
f" 当前日统计(错乱): {r['before_daily_amount']:.2f} 元 / {r['before_daily_count']}"
f' 错乱前日统计: {r["before_daily_amount"]:.2f} 元 / {r["before_daily_count"]}'
)
self.stdout.write(
f"幂等日志: {r['before_log_amount']:.2f} 元 / {r['before_log_count']}"
f'幂等日志: {r["before_log_amount"]:.2f} 元 / {r["before_log_count"]}'
)
self.stdout.write(self.style.SUCCESS(
f" 重建后(真实支付): {r['after_amount']:.2f} 元 / {r['after_count']}"
f' 重建后(正确值): {r["after_amount"]:.2f} 元 / {r["after_count"]}'
))
if r['items'] and dry_run:
self.stdout.write(' 明细前20笔:')
for ref, cid, amt, kind in r['items'][:20]:
if r['items']:
self.stdout.write(' 明细:')
for ref, cid, amt, kind in r['items']:
self.stdout.write(f' {ref} {amt}元 club={cid} ({kind})')
if len(r['items']) > 20:
self.stdout.write(f' ... 共 {len(r["items"])}')
if dry_run:
self.stdout.write(self.style.WARNING(
'\n预览完成。若重建后金额正确,执行:\n'
' python manage.py recover_wechat_income_stats --yes\n'
'指定日期:\n'
' python manage.py recover_wechat_income_stats --date 2026-06-24 --yes'
))
else:
if not dry_run and options['rebuild_all_daily']:
n = rebuild_all_daily_income_from_logs()
self.stdout.write(self.style.SUCCESS(f'已按日志全量重写 daily_income_stat: {n}'))
if not dry_run:
agg = DailyIncomeStat.objects.filter(date=end_day).aggregate(
amt=Sum('total_amount'),
cnt=Sum('total_count'),
)
self.stdout.write(self.style.SUCCESS(
'\n恢复完成。请刷新后台财务页核对今日收入。'
'\n勿再执行 repair_wechat_income已禁用'
f'\n数据库今日日统计现为: {float(agg["amt"] or 0):.2f} 元 / {int(agg["cnt"] or 0)}'
))
self.stdout.write(self.style.SUCCESS('恢复完成,请刷新后台财务页。'))
else:
self.stdout.write(self.style.WARNING(
'\n预览完成。重建后金额对的话执行:\n'
' python manage.py recover_wechat_income_stats --yes\n'
'累计总收入仍不对再加:\n'
' python manage.py recover_wechat_income_stats --yes --rebuild-all-daily'
))