kdrug-inventory-system/scripts/reset_operational_data.py
시골약사 69be63d00d docs: 제품 3단계분류 문서 추가, DB 초기화/복원 스크립트
- 제품 3단계분류.md: 성분→제품→로트 분류 체계, AI display_name 채우기 절차
- reset_operational_data.py: 마스터 보존 + 운영 데이터 초기화
- restore_backup.py: 백업 선택 복원 스크립트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:42:31 +00:00

172 lines
5.3 KiB
Python

#!/usr/bin/env python3
"""
운영 데이터 초기화 스크립트
- 마스터 데이터는 보존
- 운영/거래 데이터만 삭제
- prescription_rules 중복 정리
실행: python3 scripts/reset_operational_data.py
"""
import sqlite3
import os
from datetime import datetime
DB_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'database', 'kdrug.db')
# ============================================================
# 보존할 마스터 테이블 (절대 건드리지 않음)
# ============================================================
MASTER_TABLES = [
'herb_masters', # 454 - 급여 한약재 성분코드 마스터
'herb_master_extended', # 454 - 약재 확장 정보 (성미귀경, 효능)
'herb_products', # 53,769 - 보험 제품 목록
'product_companies', # 128 - 제조/유통사
'official_formulas', # 100 - 100처방 원방 마스터
'official_formula_ingredients', # 68 - 100처방 구성 약재
'herb_efficacy_tags', # 18 - 효능 태그 정의
'herb_item_tags', # 22 - 약재-태그 매핑
'survey_templates', # 56 - 설문 템플릿
]
# ============================================================
# 삭제할 운영 데이터 테이블 (FK 순서 고려 — 자식 먼저)
# ============================================================
CLEAR_TABLES = [
# 조제/판매 하위
'compound_consumptions',
'compound_ingredients',
'sales_status_history',
'sales_transactions',
'mileage_transactions',
# 조제 마스터
'compounds',
# 재고 하위
'stock_ledger',
'stock_adjustment_details',
'stock_adjustments',
'lot_variants',
'inventory_lots',
'inventory_lots_v2',
# 입고 하위
'purchase_receipt_lines',
'purchase_receipts',
# 처방
'formula_ingredients',
'formula_ingredients_backup',
'formulas',
'price_policies',
# 환자/설문
'survey_responses',
'survey_progress',
'patient_surveys',
'patients',
# 도매상/약재
'supplier_product_catalog',
'suppliers',
'herb_items',
# 규칙/로그 (재정비)
'prescription_rules',
'data_update_logs',
'disease_herb_mapping',
'herb_research_papers',
'herb_safety_info',
]
def reset_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("PRAGMA foreign_keys = OFF")
cursor = conn.cursor()
print(f"DB: {DB_PATH}")
print(f"시각: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print()
# 1. 마스터 테이블 행 수 확인 (보존 확인)
print("=" * 50)
print("보존 대상 마스터 테이블")
print("=" * 50)
for table in MASTER_TABLES:
try:
cursor.execute(f"SELECT COUNT(*) FROM [{table}]")
cnt = cursor.fetchone()[0]
print(f"{table}: {cnt}행 (보존)")
except:
print(f" - {table}: 테이블 없음 (skip)")
# 2. 운영 테이블 삭제
print()
print("=" * 50)
print("초기화 대상 운영 테이블")
print("=" * 50)
for table in CLEAR_TABLES:
try:
cursor.execute(f"SELECT COUNT(*) FROM [{table}]")
before = cursor.fetchone()[0]
cursor.execute(f"DELETE FROM [{table}]")
# AUTOINCREMENT 리셋
cursor.execute(f"DELETE FROM sqlite_sequence WHERE name = ?", (table,))
print(f"{table}: {before}행 → 0행")
except Exception as e:
print(f" - {table}: {e}")
# 3. prescription_rules 중복 제거 후 재삽입
print()
print("=" * 50)
print("prescription_rules 정리 (중복 제거)")
print("=" * 50)
rules = [
(298, 438, '상수', '두 약재가 함께 사용되면 보기 효과가 증강됨 (인삼+황기)', 0, 0),
(73, 358, '상수', '혈액순환 개선 효과가 증강됨 (당귀+천궁)', 0, 0),
(123, 193, '상사', '생강이 반하의 독성을 감소시킴', 0, 0),
(7, 6, '상반', '십팔반(十八反) - 함께 사용 금기', 5, 1),
(298, 252, '상반', '십구외(十九畏) - 함께 사용 주의', 4, 0),
]
for r in rules:
cursor.execute("""
INSERT INTO prescription_rules (herb1_id, herb2_id, relationship_type, description, severity_level, is_absolute)
VALUES (?, ?, ?, ?, ?, ?)
""", r)
print(f"{len(rules)}개 규칙 재삽입 (중복 제거)")
conn.commit()
conn.execute("PRAGMA foreign_keys = ON")
# 4. VACUUM
conn.execute("VACUUM")
print()
print("✓ VACUUM 완료")
# 5. 최종 확인
print()
print("=" * 50)
print("최종 상태")
print("=" * 50)
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
for row in cursor.fetchall():
table = row[0]
cursor.execute(f"SELECT COUNT(*) FROM [{table}]")
cnt = cursor.fetchone()[0]
marker = "" if cnt > 0 else " "
print(f" {marker} {table}: {cnt}")
conn.close()
print()
print("초기화 완료!")
if __name__ == '__main__':
confirm = input("운영 데이터를 모두 초기화합니다. 계속하시겠습니까? (yes/no): ")
if confirm.strip().lower() == 'yes':
reset_db()
else:
print("취소되었습니다.")