Files
Django/config/management/commands/rebuild_income_stats.py
2026-06-24 21:35:55 +08:00

71 lines
3.0 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.
"""
【终极恢复】清空全部收支脏数据,按真实微信支付逐笔重建。
只执行这一条,不要再用 repair / undo / fix
预览python manage.py rebuild_income_stats
执行python manage.py rebuild_income_stats --yes
"""
from datetime import date
from django.core.management.base import BaseCommand
from django.db.models import Sum
from config.models import DailyIncomeStat
from jituan.services.szjilu_accounting import rebuild_income_stats_from_scratch
class Command(BaseCommand):
help = '清空收支脏数据,按真实微信支付逐笔重建(终极恢复)'
def add_arguments(self, parser):
parser.add_argument('--since-year', type=int, default=0, help='从哪一年扫,默认去年')
parser.add_argument('--until-year', type=int, default=0, help='到哪一年,默认今年')
parser.add_argument('--yes', action='store_true', help='确认执行')
def handle(self, *args, **options):
until_year = options['until_year'] or date.today().year
since_year = options['since_year'] or (until_year - 1)
dry_run = not options['yes']
if dry_run:
self.stdout.write(self.style.WARNING('【预览】未改数据库\n'))
else:
self.stdout.write(self.style.ERROR(
'【执行】删除全部收入日志和日统计,按真实支付重建...\n'
))
r = rebuild_income_stats_from_scratch(
since_year=since_year, until_year=until_year, dry_run=dry_run,
)
self.stdout.write(f'=== {since_year} ~ {until_year} ===')
self.stdout.write(f' 错乱前 daily 合计: {r["before_daily_total"]:.2f}')
self.stdout.write(f' 错乱前 log: {r["before_log_total"]:.2f} 元 / {r["before_log_count"]}')
self.stdout.write(self.style.SUCCESS(
f' 重建后合计: {r["after_total"]:.2f} 元 / {r["after_count"]}'
))
self.stdout.write(self.style.SUCCESS(
f' 重建后本月: {r["month_amount"]:.2f}'
))
self.stdout.write(self.style.SUCCESS(
f' 重建后今日: {r["today_amount"]:.2f} 元 / {r["today_count"]} 笔 ← 看这条'
))
if not dry_run:
self.stdout.write(self.style.SUCCESS(
f'\ndaily 表合计: {r.get("after_daily_total", 0):.2f}'
))
agg = DailyIncomeStat.objects.filter(date=date.today()).aggregate(
amt=Sum('total_amount'), cnt=Sum('total_count'),
)
self.stdout.write(
f'今日 daily 行合计: {float(agg["amt"] or 0):.2f} 元 / {int(agg["cnt"] or 0)}'
)
self.stdout.write(self.style.SUCCESS('\n完成。刷新后台财务页。'))
else:
self.stdout.write(self.style.WARNING(
f'\n今日 {r["today_amount"]:.2f} 元对的话:\n'
f' python manage.py rebuild_income_stats --yes'
))