kdrug-inventory-system/dev_scripts/debug_api_calculation.py
시골약사 ad9ac396e2 chore: 개발 파일 정리 및 구조화
- 개발/테스트 스크립트를 dev_scripts/ 폴더로 이동
- 스크린샷을 screenshots/ 폴더로 이동
- 백업 파일 보존 (.backup)
- 처방 관련 추가 스크립트 포함

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-18 04:44:48 +00:00

115 lines
3.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
API 재고 계산 디버깅
"""
import sqlite3
def debug_api_calculation():
conn = sqlite3.connect('database/kdrug.db')
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
print("=" * 80)
print("API 재고 계산 디버깅")
print("=" * 80)
print()
# API와 동일한 쿼리 실행
cursor.execute("""
SELECT
h.herb_item_id,
h.insurance_code,
h.herb_name,
COALESCE(SUM(il.quantity_onhand), 0) as total_quantity,
COUNT(DISTINCT il.lot_id) as lot_count,
COUNT(DISTINCT il.origin_country) as origin_count,
AVG(il.unit_price_per_g) as avg_price,
MIN(il.unit_price_per_g) as min_price,
MAX(il.unit_price_per_g) as max_price,
COALESCE(SUM(il.quantity_onhand * il.unit_price_per_g), 0) as total_value
FROM herb_items h
LEFT JOIN inventory_lots il ON h.herb_item_id = il.herb_item_id AND il.is_depleted = 0
GROUP BY h.herb_item_id, h.insurance_code, h.herb_name
HAVING total_quantity > 0
ORDER BY total_value DESC
""")
items = cursor.fetchall()
print("상위 10개 약재별 재고 가치:")
print("-" * 60)
total_api_value = 0
for i, item in enumerate(items[:10], 1):
value = item['total_value']
total_api_value += value
print(f"{i:2}. {item['herb_name']:15} 재고:{item['total_quantity']:8.0f}g 금액:₩{value:10,.0f}")
# 전체 합계 계산
total_api_value = sum(item['total_value'] for item in items)
print()
print(f"전체 약재 수: {len(items)}")
print(f"API 계산 총액: ₩{total_api_value:,.0f}")
print()
# 직접 inventory_lots에서 계산
cursor.execute("""
SELECT
SUM(quantity_onhand * unit_price_per_g) as direct_total
FROM inventory_lots
WHERE is_depleted = 0 AND quantity_onhand > 0
""")
direct_total = cursor.fetchone()['direct_total'] or 0
print(f"직접 계산 총액: ₩{direct_total:,.0f}")
print(f"차이: ₩{total_api_value - direct_total:,.0f}")
print()
# 차이 원인 분석
if abs(total_api_value - direct_total) > 1:
print("차이 원인 분석:")
print("-" * 40)
# 중복 LOT 확인
cursor.execute("""
SELECT
h.herb_name,
COUNT(*) as lot_count,
SUM(il.quantity_onhand * il.unit_price_per_g) as total_value
FROM herb_items h
JOIN inventory_lots il ON h.herb_item_id = il.herb_item_id
WHERE il.is_depleted = 0 AND il.quantity_onhand > 0
GROUP BY h.herb_item_id
HAVING lot_count > 1
ORDER BY total_value DESC
LIMIT 5
""")
multi_lots = cursor.fetchall()
if multi_lots:
print("\n여러 LOT을 가진 약재:")
for herb in multi_lots:
print(f" - {herb['herb_name']}: {herb['lot_count']}개 LOT, ₩{herb['total_value']:,.0f}")
# 특이사항 확인 - LEFT JOIN으로 인한 NULL 처리
cursor.execute("""
SELECT COUNT(*) as herbs_without_lots
FROM herb_items h
LEFT JOIN inventory_lots il ON h.herb_item_id = il.herb_item_id
AND il.is_depleted = 0
AND il.quantity_onhand > 0
WHERE il.lot_id IS NULL
""")
no_lots = cursor.fetchone()['herbs_without_lots']
if no_lots > 0:
print(f"\n재고가 없는 약재 수: {no_lots}")
conn.close()
if __name__ == "__main__":
debug_api_calculation()