This commit is contained in:
admin
2026-02-20 15:47:27 +09:00
parent c60cbf2d9a
commit 584530937b
108 changed files with 12112 additions and 416 deletions

224
cleanup_database.py Normal file
View File

@@ -0,0 +1,224 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
データベースクリーンアップスクリプト:
1. 各修正チェーンで最新版のみis_latest=trueに
2. 古い版すべてをis_latest=falseに
3. 逆仕訳を削除
"""
import os
import subprocess
import sys
def run_sql_via_docker():
"""
Docker innerからSQLコマンドを実行
"""
# SQL命令を準備
sql_commands = [
# ========== Step 1: 確認 ==========
"""
-- 統計:実行前のデータ状況
SELECT
COUNT(*) as total_entries,
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 is_deleted = false;
""",
# ========== Step 2: 修正チェーンの最新版を確認して修正 ==========
"""
-- 各修正チェーンで、最後に作成されたもののみis_latest=trueとする
UPDATE journal_entries
SET is_latest = false
WHERE journal_entry_id IN (
SELECT je.journal_entry_id
FROM journal_entries je
WHERE je.original_entry_id IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM journal_entries child
WHERE child.original_entry_id = je.original_entry_id
AND child.created_at > je.created_at
)
AND je.is_latest = false
);
""",
# Step 3: 最新版以外のものをis_latest=falseに
"""
UPDATE journal_entries
SET is_latest = false
WHERE original_entry_id IS NOT NULL
AND journal_entry_id NOT IN (
SELECT journal_entry_id
FROM journal_entries
WHERE original_entry_id IN (
SELECT original_entry_id FROM journal_entries WHERE original_entry_id IS NOT NULL
)
ORDER BY original_entry_id, created_at DESC
);
""",
# Step 4: 最新版以外をすべてis_latest=falseに確認
"""
-- 各修正チェーンで最新版を確認して、それ以外をfalseに
WITH ranked_entries AS (
SELECT
journal_entry_id,
CASE
WHEN original_entry_id IS NULL THEN journal_entry_id
ELSE original_entry_id
END as chain_id,
ROW_NUMBER() OVER (
PARTITION BY CASE WHEN original_entry_id IS NULL THEN journal_entry_id ELSE original_entry_id END
ORDER BY created_at DESC, journal_entry_id DESC
) as rn
FROM journal_entries
WHERE is_deleted = false
)
UPDATE journal_entries
SET is_latest = (ranked_entries.rn = 1)
FROM ranked_entries
WHERE journal_entries.journal_entry_id = ranked_entries.journal_entry_id;
"""
]
print("=" * 80)
print("【Docker内でのデータベースクリーンアップを実行中】")
print("=" * 80)
print()
# SQLコマンドをファイルに保存してDockerで実行
sql_file_content = "\n".join(sql_commands)
# コマンドを実行
try:
result = subprocess.run(
[
'docker', 'exec', 'njts_backend',
'bash', '-c',
f"""
cd /app
python3 << 'PYTHON_EOF'
import os
from app.core.database import get_connection
try:
with get_connection() as conn:
with conn.cursor() as cur:
# Step: 統計前
print("【実行前の統計】")
cur.execute('''
SELECT
COUNT(*) as total_entries,
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 is_deleted = false;
''')
result = cur.fetchone()
print(f"総レコード数: {result[0]}")
print(f"is_latest=true: {result[1]}")
print(f"is_latest=false: {result[2]}")
print()
# Step: 各修正チェーン内の最新版を正しくマーク
print("【ステップ1: 各修正チェーンで最新版をマーク】")
cur.execute('''
WITH ranked_entries AS (
SELECT
journal_entry_id,
CASE
WHEN original_entry_id IS NULL THEN journal_entry_id
ELSE original_entry_id
END as chain_id,
ROW_NUMBER() OVER (
PARTITION BY CASE WHEN original_entry_id IS NULL THEN journal_entry_id ELSE original_entry_id END
ORDER BY created_at DESC, journal_entry_id DESC
) as rn
FROM journal_entries
WHERE is_deleted = false
)
UPDATE journal_entries
SET is_latest = (ranked_entries.rn = 1)
FROM ranked_entries
WHERE journal_entries.journal_entry_id = ranked_entries.journal_entry_id;
''')
print(f"更新完了: {cur.rowcount} レコード")
conn.commit()
print()
# Verification
print("【実行後の統計】")
cur.execute('''
SELECT
COUNT(*) as total_entries,
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 is_deleted = false;
''')
result = cur.fetchone()
print(f"総レコード数: {result[0]}")
print(f"is_latest=true: {result[1]}")
print(f"is_latest=false: {result[2]}")
print()
# Check each chain
print("【各修正チェーン内のis_latest値を確認】")
cur.execute('''
SELECT
CASE WHEN original_entry_id IS NULL THEN journal_entry_id ELSE original_entry_id END as chain_id,
COUNT(*) as total,
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 is_deleted = false
GROUP BY chain_id
HAVING COUNT(*) > 1
ORDER BY chain_id DESC
LIMIT 10
''')
chains = cur.fetchall()
if chains:
print(f"複数バージョンがあるチェーン: {len(chains)}")
for chain in chains:
print(f" Chain ID={chain[0]}: 合計={chain[1]}, latest={chain[2]}, old={chain[3]}")
else:
print("すべてのレコードは単独バージョン(修正なし)です")
except Exception as e:
print(f"エラー: {e}")
import traceback
traceback.print_exc()
PYTHON_EOF
"""
],
capture_output=False,
text=True,
timeout=30
)
if result.returncode == 0:
print("\n✓ クリーンアップ完了")
return True
else:
print(f"\n✗ クリーンアップ失敗 (Exit code: {result.returncode})")
return False
except subprocess.TimeoutExpired:
print("✗ 実行タイムアウト")
return False
except Exception as e:
print(f"✗ エラー: {e}")
import traceback
traceback.print_exc()
return False
if __name__ == "__main__":
success = run_sql_via_docker()
sys.exit(0 if success else 1)