import os os.environ['DB_HOST'] = '192.168.0.61' os.environ['DB_PORT'] = '55432' os.environ['DB_NAME'] = 'njts_acct' os.environ['DB_USER'] = 'njts_app' os.environ['DB_PASSWORD'] = 'njts_app2025' import sys sys.path.insert(0, os.path.dirname(__file__)) from app.core.database import get_connection conn = get_connection() cur = conn.cursor() print("\n" + "="*120) print("試算表ロジック検証 - 普通預金(102) 2025年6月") print("="*120) # 試算表SQLと同じロジックで集計 cur.execute(""" SELECT jl.account_id, SUM(jl.debit) as total_debit, SUM(jl.credit) as total_credit FROM journal_entries je JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id JOIN accounts a ON jl.account_id = a.account_id WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30' AND je.description <> '前期残高' AND je.is_deleted = false AND child.journal_entry_id IS NULL AND a.account_code = '102' GROUP BY jl.account_id """) result = cur.fetchone() print(f"\n【試算表の集計結果】") print(f"借方発生額: {result['total_debit']:>15,.0f} 円") print(f"貸方発生額: {result['total_credit']:>15,.0f} 円") # 詳細な内訳を確認 print(f"\n{'='*120}") print("【集計対象の仕訳詳細】") print(f"{'='*120}") cur.execute(""" SELECT je.journal_entry_id, je.entry_date, je.description, jl.debit, jl.credit, je.parent_entry_id, CASE WHEN child.journal_entry_id IS NOT NULL THEN 'Y' ELSE 'N' END as has_child FROM journal_entries je JOIN journal_lines jl ON jl.journal_entry_id = je.journal_entry_id LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id JOIN accounts a ON jl.account_id = a.account_id WHERE je.entry_date BETWEEN '2025-06-01' AND '2025-06-30' AND je.description <> '前期残高' AND je.is_deleted = false AND a.account_code = '102' ORDER BY je.journal_entry_id """) rows = cur.fetchall() debit_sum = 0 credit_sum = 0 debit_included = 0 credit_included = 0 print(f"\n{'ID':>3} {'日付':10} {'借方':>13} {'貸方':>13} {'親ID':>5} {'子':3} {'集計':4} 摘要") print("-" * 120) for r in rows: is_included = r['has_child'] == 'N' status = "○" if is_included else "×" debit_sum += r['debit'] credit_sum += r['credit'] if is_included: debit_included += r['debit'] credit_included += r['credit'] parent_str = str(r['parent_entry_id']) if r['parent_entry_id'] else "-" # 逆仕訳・修正後をマーク desc = r['description'][:60] if '[逆仕訳]' in desc: desc = f"🔄 {desc}" elif '【修正後】' in desc: desc = f"✏️ {desc}" print(f"{r['journal_entry_id']:3d} {r['entry_date']} {r['debit']:>13,.0f} {r['credit']:>13,.0f} {parent_str:>5} {r['has_child']:3} {status:4} {desc}") print("-" * 120) print(f"{'全仕訳合計':62} {debit_sum:>13,.0f} {credit_sum:>13,.0f}") print(f"{'集計対象(子なし)':60} {debit_included:>13,.0f} {credit_included:>13,.0f}") # parent_entry_idの問題を確認 print(f"\n{'='*120}") print("【parent_entry_idチェーン確認】") print(f"{'='*120}") cur.execute(""" SELECT je.journal_entry_id as id, je.description, je.parent_entry_id as parent, (SELECT description FROM journal_entries WHERE journal_entry_id = je.parent_entry_id) as parent_desc, (SELECT COUNT(*) FROM journal_entries child WHERE child.parent_entry_id = je.journal_entry_id) as child_count FROM journal_entries je WHERE (je.description LIKE '%社会保険%' OR je.description LIKE '%遠達ビル%') AND je.entry_date BETWEEN '2025-06-01' AND '2025-06-30' ORDER BY je.journal_entry_id """) print(f"\n{'ID':>3} {'親ID':>5} {'子数':>4} 摘要 → 親の摘要") print("-" * 120) rows = cur.fetchall() for r in rows: parent_str = str(r['parent']) if r['parent'] else "-" parent_desc_str = r['parent_desc'][:40] if r['parent_desc'] else "-" print(f"{r['id']:3d} {parent_str:>5} {r['child_count']:>4} {r['description'][:50]}") if r['parent_desc']: print(f" └→ 親: {parent_desc_str}") cur.close() conn.close() print(f"\n{'='*120}") print("【結論】") print(f"{'='*120}") print(""" 正しい集計方法: 1. parent_entry_idチェーンが正しく設定されている場合 → 最後の修正版のみが「子を持たない」状態になり、それのみが集計される 2. parent_entry_idの設定ミスがある場合 → 逆仕訳や途中の修正版も「子を持たない」と判定され、重複集計される 対策: - すべてのparent_entry_idを正しく設定する - チェーン: 元 → 逆仕訳 → 修正後 → 逆仕訳 → 修正後 → ... """)