""" 恢复 daily_income_stat(每日收入统计表)全表数据。 repair_wechat_income 对该表的破坏: - 把扫描到的每笔订单/充值重复写入 daily_income_stat - 金额记到「执行命令那天」,不是真实支付日 - 含退款单(Status=5)也被当成收入加进去 本命令按 platform_income_log + 无日志的已支付单,重建整张 daily_income_stat。 不碰 daily_payout_stat,不碰 szjilu,不删订单。 预览:python manage.py restore_finance_stats 执行:python manage.py restore_finance_stats --yes """ from datetime import date from django.core.management.base import BaseCommand from django.db.models import Sum from config.models import DailyIncomeStat, DailyPayoutStat from jituan.services.szjilu_accounting import rebuild_daily_income_stat_table class Command(BaseCommand): help = '恢复 daily_income_stat 全表(财务四个板子读这张表)' def add_arguments(self, parser): parser.add_argument('--yes', action='store_true', help='确认写入数据库') def handle(self, *args, **options): dry_run = not options['yes'] if dry_run: self.stdout.write(self.style.WARNING('【预览】未改数据库\n')) else: self.stdout.write(self.style.WARNING('【执行】重建 daily_income_stat...\n')) r = rebuild_daily_income_stat_table(dry_run=dry_run) self.stdout.write(f' 支付笔数(去重): {r["payment_rows"]}') self.stdout.write(f' 其中日志: {r["from_log"]}') self.stdout.write(f' 补漏订单: {r["gap_orders"]}') self.stdout.write(f' 补漏充值: {r["gap_cz"]}') self.stdout.write(f' 日统计行数: {r["daily_rows"]}') self.stdout.write(f' 恢复前 daily 合计: {r["before_daily_total"]:.2f} 元') self.stdout.write(self.style.SUCCESS( f' 恢复后 daily 合计: {r["after_daily_total"]:.2f} 元' )) self.stdout.write(f' 其中今日收入: {r["today_amount"]:.2f} 元 / {r["today_count"]} 笔') payout_today = DailyPayoutStat.objects.filter(date=date.today()).aggregate( t=Sum('total_amount'), )['t'] or 0 self.stdout.write( f' (未动)今日支出表: {float(payout_today):.2f} 元' ) if dry_run: self.stdout.write(self.style.WARNING( '\n预览数字合理后执行:\n' ' python manage.py restore_finance_stats --yes\n' '然后 push 代码并刷新财务页。' )) else: check = DailyIncomeStat.objects.aggregate(t=Sum('total_amount'))['t'] or 0 self.stdout.write(self.style.SUCCESS( f'\n完成。数据库 daily_income_stat 合计: {float(check):.2f} 元' ))