修正
This commit is contained in:
149
check_data_integrity.py
Normal file
149
check_data_integrity.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
検查和清理逆仕訳データと不正なis_latest標記
|
||||
"""
|
||||
import psycopg
|
||||
from psycopg.rows import dict_row
|
||||
|
||||
def check_and_cleanup():
|
||||
try:
|
||||
conn = psycopg.connect(
|
||||
host="127.0.0.1",
|
||||
port=5432,
|
||||
dbname="njts_accounting",
|
||||
user="postgres",
|
||||
password="postgres",
|
||||
connect_timeout=3
|
||||
)
|
||||
|
||||
with conn:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
print("=" * 80)
|
||||
print("【ステップ1】逆仕訳データの検出")
|
||||
print("=" * 80)
|
||||
|
||||
# 検査是否存在通过反向分录来处理修改的数据
|
||||
cur.execute("""
|
||||
SELECT
|
||||
j1.journal_entry_id as original_id,
|
||||
j1.description as original_desc,
|
||||
j1.entry_date as original_date,
|
||||
j2.journal_entry_id as reverse_id,
|
||||
j2.description as reverse_desc,
|
||||
j2.entry_date as reverse_date
|
||||
FROM journal_entries j1
|
||||
JOIN journal_lines l1 ON l1.journal_entry_id = j1.journal_entry_id
|
||||
JOIN journal_entries j2 ON j1.journal_entry_id = j2.parent_entry_id
|
||||
JOIN journal_lines l2 ON l2.journal_entry_id = j2.journal_entry_id
|
||||
AND l2.account_id = l1.account_id
|
||||
AND l2.debit = l1.credit
|
||||
AND l2.credit = l1.debit
|
||||
WHERE j1.is_deleted = false
|
||||
AND j2.is_deleted = false
|
||||
GROUP BY j1.journal_entry_id, j1.description, j1.entry_date,
|
||||
j2.journal_entry_id, j2.description, j2.entry_date
|
||||
LIMIT 20
|
||||
""")
|
||||
|
||||
reverse_entries = cur.fetchall()
|
||||
if reverse_entries:
|
||||
print(f"見つかった逆仕訳ペア: {len(reverse_entries)}")
|
||||
for entry in reverse_entries:
|
||||
print(f" 元:ID={entry['original_id']} ({entry['original_desc']}) {entry['original_date']}")
|
||||
print(f" 逆:ID={entry['reverse_id']} ({entry['reverse_desc']}) {entry['reverse_date']}")
|
||||
else:
|
||||
print("逆仕訳ペアが見つかりません")
|
||||
|
||||
print()
|
||||
print("=" * 80)
|
||||
print("【ステップ2】is_latest=false だけど修正鎖に含まれない孤立記録")
|
||||
print("=" * 80)
|
||||
|
||||
cur.execute("""
|
||||
SELECT
|
||||
journal_entry_id,
|
||||
description,
|
||||
is_latest,
|
||||
is_deleted,
|
||||
parent_entry_id,
|
||||
original_entry_id,
|
||||
entry_date
|
||||
FROM journal_entries
|
||||
WHERE is_latest = false
|
||||
AND (original_entry_id IS NULL AND parent_entry_id IS NULL)
|
||||
AND is_deleted = false
|
||||
LIMIT 20
|
||||
""")
|
||||
|
||||
orphan_entries = cur.fetchall()
|
||||
if orphan_entries:
|
||||
print(f"孤立記録が見つかりました: {len(orphan_entries)}")
|
||||
for entry in orphan_entries:
|
||||
print(f" ID={entry['journal_entry_id']}: {entry['description']} (date={entry['entry_date']})")
|
||||
else:
|
||||
print("孤立記録が見つかりません")
|
||||
|
||||
print()
|
||||
print("=" * 80)
|
||||
print("【ステップ3】修正鎖の整体性確認")
|
||||
print("=" * 80)
|
||||
|
||||
# 检查是否有parent_entry_id指向不存在的記録
|
||||
cur.execute("""
|
||||
SELECT
|
||||
je.journal_entry_id,
|
||||
je.parent_entry_id,
|
||||
je.description
|
||||
FROM journal_entries je
|
||||
LEFT JOIN journal_entries parent ON parent.journal_entry_id = je.parent_entry_id
|
||||
WHERE je.parent_entry_id IS NOT NULL
|
||||
AND parent.journal_entry_id IS NULL
|
||||
LIMIT 20
|
||||
""")
|
||||
|
||||
broken_links = cur.fetchall()
|
||||
if broken_links:
|
||||
print(f"破损されたリンク が見つかりました: {len(broken_links)}")
|
||||
for entry in broken_links:
|
||||
print(f" ID={entry['journal_entry_id']}: 削除されたparen_entry_id={entry['parent_entry_id']}")
|
||||
else:
|
||||
print("破损されたリンクが見つかりません")
|
||||
|
||||
print()
|
||||
print("=" * 80)
|
||||
print("【ステップ4】修正被修改的还有没有更新成正确is_latest的记录")
|
||||
print("=" * 80)
|
||||
|
||||
# 检查是否有多个is_latest=true在同一修正鎖中
|
||||
cur.execute("""
|
||||
SELECT
|
||||
original_entry_id,
|
||||
COUNT(*) as total_count,
|
||||
SUM(CASE WHEN is_latest = true THEN 1 ELSE 0 END) as latest_count,
|
||||
SUM(CASE WHEN is_latest = false THEN 1 ELSE 0 END) as old_count
|
||||
FROM journal_entries
|
||||
WHERE original_entry_id IS NOT NULL
|
||||
GROUP BY original_entry_id
|
||||
HAVING SUM(CASE WHEN is_latest = true THEN 1 ELSE 0 END) != 1
|
||||
""")
|
||||
|
||||
bad_chains = cur.fetchall()
|
||||
if bad_chains:
|
||||
print(f"不正合な修正鎖が見つかりました: {len(bad_chains)}")
|
||||
for chain in bad_chains:
|
||||
print(f" original_id={chain['original_entry_id']}: 合計={chain['total_count']}, latest={chain['latest_count']}, old={chain['old_count']}")
|
||||
else:
|
||||
print("正常な修正鎖のみです")
|
||||
|
||||
conn.close()
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"エラー: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_and_cleanup()
|
||||
Reference in New Issue
Block a user