- 개발/테스트 스크립트를 dev_scripts/ 폴더로 이동 - 스크린샷을 screenshots/ 폴더로 이동 - 백업 파일 보존 (.backup) - 처방 관련 추가 스크립트 포함 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
115 lines
3.6 KiB
Python
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() |