修正
This commit is contained in:
142
identify_all_duplicates.py
Normal file
142
identify_all_duplicates.py
Normal file
@@ -0,0 +1,142 @@
|
||||
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("=" * 140)
|
||||
print("【识别可能的6月→7月/8月复制数据】")
|
||||
print("=" * 140)
|
||||
|
||||
# 第1步:找出6月所有有的仕訳(描述+金额的组合)
|
||||
print("\n第1步:提取6月的所有仕訳(描述和金额作为KEY)")
|
||||
|
||||
cur.execute("""
|
||||
SELECT DISTINCT
|
||||
je.description,
|
||||
COALESCE(SUM(jl.debit), 0)::BIGINT as total_debit,
|
||||
COALESCE(SUM(jl.credit), 0)::BIGINT as total_credit
|
||||
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) = 6
|
||||
GROUP BY je.journal_entry_id, je.description
|
||||
ORDER BY je.description
|
||||
""")
|
||||
|
||||
june_patterns = cur.fetchall()
|
||||
print(f"找到 {len(june_patterns)} 个6月的仕訳模式")
|
||||
|
||||
# 第2步:在7月和8月中查找相同的仕訳
|
||||
print("\n第2步:在7月和8月中查找相同描述和金额的仕訳")
|
||||
|
||||
duplicates_for_deletion = []
|
||||
|
||||
for description, debit, credit in june_patterns:
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
TO_CHAR(je.entry_date, 'YYYY-MM-DD') as entry_date,
|
||||
EXTRACT(MONTH FROM je.entry_date)::INT as month,
|
||||
COALESCE(SUM(jl.debit), 0)::BIGINT as calc_debit,
|
||||
COALESCE(SUM(jl.credit), 0)::BIGINT as calc_credit
|
||||
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)
|
||||
AND je.description = %s
|
||||
GROUP BY je.journal_entry_id, je.entry_date
|
||||
HAVING COALESCE(SUM(jl.debit), 0) = %s
|
||||
AND COALESCE(SUM(jl.credit), 0) = %s
|
||||
""", (description, debit, credit))
|
||||
|
||||
matches = cur.fetchall()
|
||||
if matches:
|
||||
for entry_id, entry_date, month, calc_debit, calc_credit in matches:
|
||||
duplicates_for_deletion.append({
|
||||
'entry_id': entry_id,
|
||||
'date': entry_date,
|
||||
'month': month,
|
||||
'description': description,
|
||||
'debit': debit,
|
||||
'credit': credit
|
||||
})
|
||||
|
||||
# 按月份排序
|
||||
duplicates_for_deletion.sort(key=lambda x: (x['month'], x['entry_id']))
|
||||
|
||||
print(f"\n找到 {len(duplicates_for_deletion)} 个可能的复制记录(7月/8月中与6月相同的)")
|
||||
|
||||
if duplicates_for_deletion:
|
||||
print("\n【可能的复制记录列表】\n")
|
||||
|
||||
current_month = None
|
||||
for dup in duplicates_for_deletion:
|
||||
if dup['month'] != current_month:
|
||||
print(f"\n--- {dup['month']}月 ---")
|
||||
current_month = dup['month']
|
||||
|
||||
print(f"ID={dup['entry_id']:3d} | {dup['date']} | 借={dup['debit']:>12,} 貸={dup['credit']:>12,}")
|
||||
print(f" └─ {dup['description'][:80]}")
|
||||
|
||||
print("\n" + "=" * 140)
|
||||
print(f"【预期删除】{len(duplicates_for_deletion)} 条记录")
|
||||
print("=" * 140)
|
||||
|
||||
# 计算删除前后的普通預金期末残高变化
|
||||
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 dup 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 -- 普通預金
|
||||
""", (dup['entry_id'],))
|
||||
|
||||
impact = cur.fetchone()[0]
|
||||
deletion_impact += impact
|
||||
|
||||
expected_balance_after = current_balance - deletion_impact
|
||||
|
||||
print(f"这些记录对普通預金的总影响: {deletion_impact:>15,.0f}円")
|
||||
print(f"删除后预期普通預金期末残高: {expected_balance_after:>15,.0f}円")
|
||||
print(f"\n期望目标值: 14,916,322円")
|
||||
print(f"删除后vs目标值差距: {14_916_322 - expected_balance_after:>15,.0f}円")
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
||||
# 保存删除列表到Python变量以供后续使用
|
||||
print("\n" + "=" * 140)
|
||||
print(f"识别完成。找到 {len(duplicates_for_deletion)} 条可能的复制记录")
|
||||
print("=" * 140)
|
||||
|
||||
# 返回delete_list供后续使用
|
||||
import json
|
||||
print("\n【识别的删除对象IDs】")
|
||||
delete_ids = [dup['entry_id'] for dup in duplicates_for_deletion]
|
||||
print(delete_ids)
|
||||
Reference in New Issue
Block a user