fix: 恢复 repair 重复记账 + 禁用错误补账命令
This commit is contained in:
85
config/management/commands/recover_wechat_income_stats.py
Normal file
85
config/management/commands/recover_wechat_income_stats.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""
|
||||
恢复被 repair_wechat_income 搞乱的收入统计。
|
||||
|
||||
repair 会对已入账订单重复加钱(200 变 900 就是这个)。
|
||||
本命令:删掉当日错误日志 → 按真实微信支付重建 → 重算日统计和 szjilu。
|
||||
|
||||
先不加 --yes 可预览重建后金额。
|
||||
"""
|
||||
from datetime import date, timedelta
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from jituan.services.szjilu_accounting import recover_income_stats_for_date
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
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='从指定日期起向前恢复几天,默认 1',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--yes',
|
||||
action='store_true',
|
||||
help='确认执行(不加则仅预览,不改数据库)',
|
||||
)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if options['date']:
|
||||
end_day = date.fromisoformat(options['date'])
|
||||
else:
|
||||
end_day = date.today()
|
||||
days = max(1, int(options['days'] or 1))
|
||||
start_day = end_day - timedelta(days=days - 1)
|
||||
dry_run = not options['yes']
|
||||
|
||||
if dry_run:
|
||||
self.stdout.write(self.style.WARNING(
|
||||
'【预览模式】未改数据库。确认金额无误后加 --yes 执行。\n'
|
||||
))
|
||||
else:
|
||||
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['before_daily_amount']:.2f} 元 / {r['before_daily_count']} 笔"
|
||||
)
|
||||
self.stdout.write(
|
||||
f" 当前幂等日志: {r['before_log_amount']:.2f} 元 / {r['before_log_count']} 笔"
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
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]:
|
||||
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:
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
'\n恢复完成。请刷新后台财务页核对今日收入。'
|
||||
'\n勿再执行 repair_wechat_income(已禁用)。'
|
||||
))
|
||||
Reference in New Issue
Block a user