import psycopg2 conn = psycopg2.connect( host="192.168.0.61", port=55432, database="njts_acct", user="njts_app", password="njts_app2025" ) cur = conn.cursor() print("=" * 160) print("【方法3:在7月/8月中,同一月份有多个相同描述和金额的仕訳】") print("=" * 160) print("\n这种情况通常表示错误的重复输入,应该保留1条,删除其余\n") # 找出在7月/8月中,同一月份有多个相同描述和金额的仕訳 cur.execute(""" WITH july_august_with_counts AS ( SELECT je.journal_entry_id, je.entry_date, EXTRACT(MONTH FROM je.entry_date)::INT as month, je.description, COALESCE(SUM(jl.debit), 0)::BIGINT as total_debit, COALESCE(SUM(jl.credit), 0)::BIGINT as total_credit, ROW_NUMBER() OVER (PARTITION BY EXTRACT(MONTH FROM je.entry_date), je.description, COALESCE(SUM(jl.debit), 0), COALESCE(SUM(jl.credit), 0) ORDER BY je.journal_entry_id) as rn, COUNT(*) OVER (PARTITION BY EXTRACT(MONTH FROM je.entry_date), je.description, COALESCE(SUM(jl.debit), 0), COALESCE(SUM(jl.credit), 0)) as cnt FROM journal_entries je LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id WHERE je.is_deleted = false AND je.is_latest = true AND EXTRACT(YEAR FROM je.entry_date) = 2025 AND EXTRACT(MONTH FROM je.entry_date) IN (7, 8) GROUP BY je.journal_entry_id, je.entry_date, je.description ) SELECT month, description, total_debit, total_credit, cnt, STRING_AGG(journal_entry_id::TEXT || '(' || TO_CHAR(entry_date, 'MM-DD') || ')', ', ' ORDER BY journal_entry_id) as ids FROM july_august_with_counts WHERE cnt > 1 GROUP BY month, description, total_debit, total_credit, cnt ORDER BY cnt DESC, month, description """) duplicates_in_month = cur.fetchall() print(f"找到 {len(duplicates_in_month)} 个在同一月份有重复的仕訳模式\n") duplicates_for_deletion = [] for month, description, debit, credit, cnt, ids in duplicates_in_month: print(f"【{cnt}重複!】{month}月 | 借={debit:>12,} 貸={credit:>12,}") print(f" 説明: {description}") print(f" IDs: {ids}") print() # 对于每个重复的模式,删除除了第一个外的其他记录 cur.execute(""" WITH duplicates AS ( SELECT je.journal_entry_id, ROW_NUMBER() OVER (PARTITION BY EXTRACT(MONTH FROM je.entry_date), je.description, COALESCE(SUM(jl.debit), 0), COALESCE(SUM(jl.credit), 0) ORDER BY je.journal_entry_id) as rn FROM journal_entries je LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id WHERE je.is_deleted = false AND je.is_latest = true AND EXTRACT(YEAR FROM je.entry_date) = 2025 AND EXTRACT(MONTH FROM je.entry_date) = %s AND je.description = %s GROUP BY je.journal_entry_id, je.entry_date, je.description ) SELECT journal_entry_id FROM duplicates WHERE rn > 1 ORDER BY journal_entry_id """, (month, description)) to_delete = cur.fetchall() for (entry_id,) in to_delete: duplicates_for_deletion.append(entry_id) print(f" ├─ 删除: ID={entry_id}") print("\n" + "=" * 160) print(f"【汇总】共 {len(duplicates_for_deletion)} 条重复记录需要删除") print("=" * 160) if duplicates_for_deletion: print(f"\n要删除的IDs: {duplicates_for_deletion}") # 计算删除影响 cur.execute(""" SELECT COALESCE(SUM(COALESCE(jl.debit, 0) - COALESCE(jl.credit, 0)), 0) as balance FROM journal_lines jl INNER JOIN journal_entries je ON jl.journal_entry_id = je.journal_entry_id WHERE jl.account_id = 2 AND je.is_deleted = false AND je.is_latest = true """) current_balance = cur.fetchone()[0] print(f"\n删除前普通預金期末残高: {current_balance:>15,.0f}円") # 计算影响 deletion_impact = 0 for entry_id in duplicates_for_deletion: cur.execute(""" SELECT COALESCE(SUM(COALESCE(jl.debit, 0) - COALESCE(jl.credit, 0)), 0) FROM journal_lines jl WHERE jl.journal_entry_id = %s AND jl.account_id = 2 """, (entry_id,)) impact = cur.fetchone()[0] deletion_impact += impact expected_after = current_balance - deletion_impact print(f"普通預金的总变化: -{deletion_impact:>15,.0f}円") print(f"删除后普通預金期末残高: {expected_after:>15,.0f}円") print(f"\n期望目标值: 14,916,322円") if expected_after == 14_916_322: print(f"✓ 完美匹配!") else: diff = 14_916_322 - expected_after if diff > 0: print(f"∆ 删除后仍低于目标: {diff:>15,.0f}円") else: print(f"∆ 删除后高于目标: {-diff:>15,.0f}円") else: print("\n没有找到单月内的重复记录") cur.close() conn.close()