#!/usr/bin/env python # -*- coding: utf-8 -*- import os import sys sys.path.insert(0, 'backend') os.environ['DB_HOST'] = '192.168.0.61' os.environ['DB_NAME'] = 'njts_acct' os.environ['DB_USER'] = 'njts_app' os.environ['DB_PASSWORD'] = 'njts_app2025' os.environ['DB_PORT'] = '55432' from app.core.database import get_connection with get_connection() as conn: with conn.cursor() as cur: print('\n【 檢查2025年7月和8月的問題交易 】\n') # 获取account_id cur.execute("SELECT account_id FROM accounts WHERE account_code = '701'") aid = cur.fetchone()['account_id'] for month in [7, 8]: print(f"{'='*80}") print(f"【 2025年{month}月的701科目交易 】") print(f"{'='*80}\n") # 查找类似"【未計上のため取消】"的交易,没有parent的(可能重複) cur.execute(""" SELECT j.journal_entry_id, j.entry_date, j.description, l.debit, l.credit, j.parent_entry_id, j.is_deleted, (SELECT COUNT(*) FROM journal_entries child WHERE child.parent_entry_id = j.journal_entry_id) as has_child FROM journal_lines l JOIN journal_entries j ON j.journal_entry_id = l.journal_entry_id WHERE l.account_id = %s AND EXTRACT(MONTH FROM j.entry_date) = %s AND EXTRACT(YEAR FROM j.entry_date) = 2025 AND j.is_deleted = false ORDER BY j.entry_date, j.journal_entry_id """, (aid, month)) entries = cur.fetchall() print(f"找到交易 {len(entries)} 筆\n") print("Entry# | Date | Debit | Credit | Parent | HasChild | Description (first 40 chars)") print("-" * 100) for row in entries: parent_str = f"#{row['parent_entry_id']}" if row['parent_entry_id'] else "None" child_str = "是" if row['has_child'] > 0 else "否" desc_short = row['description'][:40] if row['description'] else "" print(f"#{row['journal_entry_id']:<5} | {row['entry_date']} | {row['debit'] or 0:>10} | {row['credit'] or 0:>10} | {parent_str:<6} | {child_str:<8} | {desc_short}") # 查找可疑的交易模式 print(f"\n【 掃描可疑模式 】\n") # 1. 查找沒有parent且金額大的【未計上のため取消】交易(重複取消) cur.execute(""" SELECT j.journal_entry_id, j.description, l.credit FROM journal_lines l JOIN journal_entries j ON j.journal_entry_id = l.journal_entry_id WHERE l.account_id = %s AND EXTRACT(MONTH FROM j.entry_date) = %s AND EXTRACT(YEAR FROM j.entry_date) = 2025 AND j.is_deleted = false AND j.parent_entry_id IS NULL AND j.description LIKE '%未計上のため取消%' AND l.credit > 500000 """, (aid, month)) duplicate_cancels = cur.fetchall() if duplicate_cancels: print(f"⚠️ 發現可能重複的取消交易(無parent但有大額貳方):\n") for row in duplicate_cancels: print(f" Entry#{row['journal_entry_id']}: {row['credit']:>12} | {row['description'][:50]}") else: print("✓ 沒有發現重複的取消交易") # 2. 查找【修正後】且是最後一個交易(葉節點)的交易(可能是Entry#373的情況) cur.execute(""" SELECT j.journal_entry_id, j.description, l.debit, j.parent_entry_id, (SELECT COUNT(*) FROM journal_entries child WHERE child.parent_entry_id = j.journal_entry_id) as has_child FROM journal_lines l JOIN journal_entries j ON j.journal_entry_id = l.journal_entry_id WHERE l.account_id = %s AND EXTRACT(MONTH FROM j.entry_date) = %s AND EXTRACT(YEAR FROM j.entry_date) = 2025 AND j.is_deleted = false AND j.description LIKE '%【修正後】%' AND l.debit > 500000 AND (SELECT COUNT(*) FROM journal_entries child WHERE child.parent_entry_id = j.journal_entry_id) = 0 """, (aid, month)) correction_leafs = cur.fetchall() if correction_leafs: print(f"\n⚠️ 發現可能的修正鏈葉節點(【修正後】且無子交易):\n") for row in correction_leafs: parent_str = f"#{row['parent_entry_id']}" if row['parent_entry_id'] else "None" print(f" Entry#{row['journal_entry_id']}: {row['debit']:>12} | parent={parent_str} | {row['description'][:45]}") else: print("✓ 沒有發現修正鏈葉節點") print("\n")