#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Delete all journal entries with "逆仕訳" in description """ import sys sys.path.insert(0, '/app') from app.core.database import get_connection def delete_reverse_entries(): with get_connection() as conn: with conn.cursor() as cur: print("=" * 80) print("【「逆仕訳」データの削除(外键制約を考慮)】") print("=" * 80) print() # Step 1: Find and list all entries with "逆仕訳" print("【ステップ1: 削除対象データを検索】") cur.execute(""" SELECT journal_entry_id, description, entry_date, is_latest FROM journal_entries WHERE description LIKE '%逆仕訳%' AND is_deleted = false ORDER BY journal_entry_id """) reverse_entries = cur.fetchall() print(f"「逆仕訳」が含まれるレコード: {len(reverse_entries)} 件") if len(reverse_entries) == 0: print("削除対象のレコードがありません") return ids_to_delete = [e['journal_entry_id'] for e in reverse_entries] # Step 2: Check for references print() print("【ステップ2: 外键参照をチェック】") cur.execute(""" SELECT DISTINCT parent_entry_id, COUNT(*) as count FROM journal_entries WHERE parent_entry_id = ANY(%s) AND is_deleted = false GROUP BY parent_entry_id """, (ids_to_delete,)) refs = cur.fetchall() if refs: print(f"参照されているレコード:") for ref in refs: print(f" ID={ref['parent_entry_id']}: {ref['count']} 個の子レコード") # Step 3: Handle references by clearing parent_entry_id print() print("【ステップ3: 参照をクリア】") cur.execute(""" UPDATE journal_entries SET parent_entry_id = NULL WHERE parent_entry_id = ANY(%s) """, (ids_to_delete,)) cleared = cur.rowcount print(f"クリアされたレコード: {cleared} 件") # Step 4: Delete journal_lines print() print("【ステップ4: ジャーナル行を削除】") cur.execute("DELETE FROM journal_lines WHERE journal_entry_id = ANY(%s)", (ids_to_delete,)) lines_deleted = cur.rowcount print(f"削除されたジャーナル行: {lines_deleted} 行") # Step 5: Delete journal_entries print() print("【ステップ5: ジャーナルエントリを削除】") cur.execute("DELETE FROM journal_entries WHERE journal_entry_id = ANY(%s)", (ids_to_delete,)) entries_deleted = cur.rowcount print(f"削除されたジャーナルエントリ: {entries_deleted} 件") conn.commit() # Step 6: Statistics print() print("【ステップ6: 削除後の統計】") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false") total = cur.fetchone()['count'] print(f"総レコード数: {total}") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false AND is_latest = true") latest = cur.fetchone()['count'] print(f" is_latest=true: {latest}") cur.execute("SELECT COUNT(*) FROM journal_entries WHERE is_deleted = false AND is_latest = false") old = cur.fetchone()['count'] print(f" is_latest=false: {old}") # Step 7: Verify 2025年6月 sales revenue print() print("【ステップ7: 2025年6月の売上高を再確認】") cur.execute(""" SELECT SUM(l.debit) as total_debit, SUM(l.credit) as total_credit FROM journal_lines l JOIN journal_entries j ON j.journal_entry_id = l.journal_entry_id JOIN accounts a ON a.account_id = l.account_id WHERE a.account_code = '701' AND EXTRACT(YEAR FROM j.entry_date) = 2025 AND EXTRACT(MONTH FROM j.entry_date) = 6 AND j.is_deleted = false AND j.is_latest = true """) result = cur.fetchone() print(f"2025年6月 売上高(最新版のみ):") print(f" 借方: {result['total_debit']:>12,.0f}") print(f" 貸方: {result['total_credit']:>12,.0f}") print() print("✓ 削除完了") if __name__ == "__main__": try: delete_reverse_entries() except Exception as e: print(f"エラー: {e}") import traceback traceback.print_exc() sys.exit(1)