#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Cleanup script for running inside Docker container """ import os import sys # Add current dir to path so we can import app sys.path.insert(0, '/app') from app.core.database import get_connection def cleanup(): with get_connection() as conn: with conn.cursor() as cur: print("=" * 80) print("【データベースクリーンアップ】") print("=" * 80) print() # Step 1: Find orphan reverse entries print("【ステップ1: 削除対象となる逆仕訳を検索】") cur.execute(""" SELECT journal_entry_id, description, entry_date, is_latest FROM journal_entries WHERE is_deleted = false AND is_latest = false AND parent_entry_id IS NULL AND original_entry_id IS NULL ORDER BY created_at DESC """) rows = cur.fetchall() print(f" 見つかったレコード: {len(rows)} 件") for i, r in enumerate(rows[:5]): print(f" {i+1}. ID={r['journal_entry_id']}: {r['description']} ({r['entry_date']})") if len(rows) > 5: print(f" ... 他 {len(rows)-5} 件") if len(rows) > 0: print() print("【ステップ2: レコードを削除】") ids = [r['journal_entry_id'] for r in rows] # Delete journal_lines first cur.execute("DELETE FROM journal_lines WHERE journal_entry_id = ANY(%s)", (ids,)) lines_cnt = cur.rowcount # Delete journal_entries cur.execute("DELETE FROM journal_entries WHERE journal_entry_id = ANY(%s)", (ids,)) entries_cnt = cur.rowcount conn.commit() print(f" 削除完了: {entries_cnt} 仕訳エントリ, {lines_cnt} 仕訳行") else: print(" 削除対象のレコードがありません") print() print("【ステップ3: クリーンアップ後の統計】") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false") total = cur.fetchone() print(f" 総レコード数: {total['count']}") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false AND is_latest = true") latest = cur.fetchone() print(f" is_latest=true: {latest['count']}") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false AND is_latest = false") old = cur.fetchone() print(f" is_latest=false: {old['count']}") # Check data integrity print() print("【データ整合性の確認】") cur.execute(""" SELECT COALESCE(original_entry_id, journal_entry_id) as chain_id, COUNT(*) as total, SUM(CASE WHEN is_latest = true THEN 1 ELSE 0 END) as latest_cnt FROM journal_entries WHERE is_deleted = false GROUP BY COALESCE(original_entry_id, journal_entry_id) HAVING COUNT(*) > 1 """) chains = cur.fetchall() print(f" 複数バージョンのチェーン: {len(chains)} 件") if chains: for chain in chains[:3]: print(f" Chain {chain['chain_id']}: 合計={chain['total']}, latest={chain['latest_cnt']}") print() print("✓ クリーンアップ完了") if __name__ == "__main__": try: cleanup() except Exception as e: print(f"エラー: {e}") import traceback traceback.print_exc() sys.exit(1)