Files
njts-accounting-core/fix_revision_links.py
2026-02-20 15:47:27 +09:00

173 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
修复数据库中的版本链接错误和is_latest标记
"""
import psycopg
from datetime import datetime
try:
conn = psycopg.connect(
host='192.168.0.61',
port=55432,
dbname='njts_acct',
user='njts_app',
password='njts_app2025'
)
with conn.cursor() as cur:
print("=" * 70)
print("【数据库修复版本链接和is_latest标记】")
print("=" * 70)
# 第一步:识别【修正後】記錄,並確保其 original_entry_id 指向真正的原始版本
print("\n【步驟 1】修復 original_entry_id 鏈接...")
# 查找所有【修正後】的記錄
cur.execute("""
SELECT journal_entry_id, description, original_entry_id
FROM journal_entries
WHERE description LIKE '%【修正後】%'
AND is_deleted = false
ORDER BY journal_entry_id
""")
corrupted_count = 0
for row in cur.fetchall():
je_id, desc, orig_id = row
# 如果original_entry_id指向另一个【修正後】記錄就往上追溯
if orig_id:
cur.execute("""
SELECT original_entry_id, description
FROM journal_entries
WHERE journal_entry_id = %s
""", (orig_id,))
parent_row = cur.fetchone()
if parent_row:
parent_orig_id, parent_desc = parent_row
# 如果指向的記錄也是【修正後】,說明有鏈接錯誤
if '【修正後】' in parent_desc and parent_orig_id and parent_orig_id != orig_id:
print(f"\n修復 ID={je_id}: {desc[:30]}")
print(f" 舊的 original_entry_id: {orig_id} (也是【修正後】記錄)")
print(f" 新的 original_entry_id: {parent_orig_id}")
cur.execute("""
UPDATE journal_entries
SET original_entry_id = %s
WHERE journal_entry_id = %s
""", (parent_orig_id, je_id))
corrupted_count += 1
conn.commit()
if corrupted_count > 0:
print(f"\n✓ 已修復 {corrupted_count} 條記錄的 original_entry_id")
else:
print("✓ 沒有發現 original_entry_id 鏈接錯誤")
# 第二步:重新設置 is_latest 標記
print("\n【步驟 2】重新設置 is_latest 標記...")
# 清空所有 is_latest 標記
cur.execute("UPDATE journal_entries SET is_latest = false WHERE is_deleted = false")
conn.commit()
# 對每條版本鏈,只有最新版本的 is_latest = true
cur.execute("""
SELECT DISTINCT original_entry_id FROM journal_entries
WHERE original_entry_id IS NOT NULL AND is_deleted = false
UNION
SELECT DISTINCT journal_entry_id FROM journal_entries
WHERE original_entry_id IS NULL AND is_deleted = false
AND journal_entry_id NOT IN (
SELECT original_entry_id FROM journal_entries WHERE original_entry_id IS NOT NULL
)
""")
chain_heads = [row[0] for row in cur.fetchall()]
updated_count = 0
for chain_head in chain_heads:
# 找出這條鏈中最新的版本(根據 created_at 或 journal_entry_id
cur.execute("""
SELECT journal_entry_id FROM journal_entries
WHERE (journal_entry_id = %s OR original_entry_id = %s)
AND is_deleted = false
ORDER BY journal_entry_id DESC
LIMIT 1
""", (chain_head, chain_head))
latest = cur.fetchone()
if latest:
latest_id = latest[0]
cur.execute("""
UPDATE journal_entries
SET is_latest = true
WHERE journal_entry_id = %s
""", (latest_id,))
updated_count += 1
conn.commit()
print(f"✓ 已設置 {updated_count} 條最新版本的 is_latest = true")
# 第三步:驗證
print("\n【步驟 3】驗證修復結果...")
print("-" * 70)
# 檢查是否有多個 is_latest=true 在同一個鏈中
cur.execute("""
SELECT original_entry_id, COUNT(*) as cnt
FROM journal_entries
WHERE is_latest = true AND is_deleted = false AND original_entry_id IS NOT NULL
GROUP BY original_entry_id
HAVING COUNT(*) > 1
""")
duplicates = cur.fetchall()
if duplicates:
print("⚠️ 警告:發現重複的 is_latest=true")
for dup in duplicates:
print(f" original_entry_id={dup[0]}: {dup[1]} 條記錄")
else:
print("✓ 沒有發現重複的 is_latest=true")
# 統計各狀態的記錄數
cur.execute("""
SELECT is_latest, COUNT(*) as cnt
FROM journal_entries
WHERE is_deleted = false
GROUP BY is_latest
""")
stats = cur.fetchall()
print("\n記錄統計:")
for stat in stats:
print(f" is_latest={stat[0]}: {stat[1]}")
# 驗證【test元】的鏈
print("\n【test 元】鏈的驗證:")
print("-" * 70)
cur.execute("""
SELECT journal_entry_id, description, is_latest, revision_count, original_entry_id
FROM journal_entries
WHERE (description LIKE '%test%' AND is_deleted = false)
AND journal_entry_id >= 410
ORDER BY journal_entry_id
""")
test_records = cur.fetchall()
for rec in test_records:
je_id, desc, is_latest, rev_cnt, orig_id = rec
status = "" if is_latest else " "
print(f"{status} ID={je_id:3d} rev={rev_cnt} orig_id={str(orig_id):>6s} {desc[:40]}")
conn.close()
print("\n" + "=" * 70)
print("修復完成!")
print("=" * 70)
except Exception as e:
print(f'錯誤: {e}')
import traceback
traceback.print_exc()