# 한약 재고관리 시스템 데이터 구조 및 흐름

> 최종 수정: 2026-02-17
> 작성자: 시스템 개발팀

## 📊 1. 전체 시스템 개요

### 1.1 시스템 목적
- 한의원의 한약재 재고 관리
- 처방 조제 및 소비 추적
- 보험 청구를 위한 코드 관리
- 효능 기반 약재 정보 관리

### 1.2 핵심 개념
```
┌─────────────────────────────────────────────┐
│  성분코드 (ingredient_code)                 │
│  - 한약재의 본질적 정체성                   │
│  - 예: "3400H1AHM" = 인삼                  │
│  - 총 454개 표준 약재                       │
└─────────────────────────────────────────────┘
                    ↓
┌─────────────────────────────────────────────┐
│  보험코드 (insurance_code)                  │
│  - 실제 청구/재고 관리 단위                 │
│  - 9자리 제품 코드                          │
│  - 예: "062400740" = 휴먼감초              │
└─────────────────────────────────────────────┘
```

## 🗂️ 2. 테이블 구조 상세

### 2.1 마스터 데이터 (Master Data)

#### **herb_masters** - 성분코드 마스터
```sql
CREATE TABLE herb_masters (
    ingredient_code VARCHAR(10) PRIMARY KEY,  -- "3400H1AHM"
    herb_name VARCHAR(100),                   -- "인삼"
    herb_name_hanja VARCHAR(100),            -- "人蔘"
    herb_name_latin VARCHAR(200)             -- "Ginseng Radix"
)
-- 역할: 454개 표준 한약재 정의
-- 특징: 보험급여 약재 목록
```

#### **herb_master_extended** - 확장 정보
```sql
CREATE TABLE herb_master_extended (
    herb_id INTEGER PRIMARY KEY AUTOINCREMENT,  -- 단순 인덱스
    ingredient_code VARCHAR(10) UNIQUE,         -- herb_masters와 1:1
    property VARCHAR(50),                       -- 성(性): 온/한/평
    taste VARCHAR(100),                         -- 미(味): 감/고/신
    meridian_tropism TEXT,                      -- 귀경: 비,폐,심
    main_effects TEXT,                          -- 주요 효능
    dosage_range VARCHAR(50)                    -- 상용량: "3-9g"
)
-- 역할: 한의학적 속성 정보 저장
-- 관계: ingredient_code로 herb_masters와 연결
```

### 2.2 제품 및 재고 (Products & Inventory)

#### **herb_products** - 제품 카탈로그
```sql
CREATE TABLE herb_products (
    product_id INTEGER PRIMARY KEY,
    ingredient_code VARCHAR(10),    -- 성분코드 (FK)
    product_code VARCHAR(9),         -- 보험코드 9자리
    company_name VARCHAR(200),       -- "휴먼허브"
    product_name VARCHAR(200)        -- "휴먼감초"
)
-- 역할: 성분코드 ↔ 보험코드 매핑
-- 특징: 여러 회사가 같은 성분을 다른 코드로 판매
```

#### **herb_items** - 재고 관리 단위
```sql
CREATE TABLE herb_items (
    herb_item_id INTEGER PRIMARY KEY,
    insurance_code VARCHAR(20),      -- 보험코드 (9자리)
    herb_name VARCHAR(100),
    ingredient_code VARCHAR(10)      -- 일부만 보유 (28/31)
)
-- 역할: 우리가 실제 보유한 약재 목록
-- 현황: 총 31개 약재 보유
```

#### **inventory_lots** - 로트별 재고
```sql
CREATE TABLE inventory_lots (
    lot_id INTEGER PRIMARY KEY,
    herb_item_id INTEGER,            -- FK to herb_items
    quantity_onhand REAL,            -- 현재 재고량(g)
    unit_price_per_g REAL,           -- g당 단가
    origin_country TEXT,             -- 원산지
    expiry_date DATE                 -- 유효기간
)
-- 역할: 실제 재고 수량 관리
-- 특징: FIFO 소비, 로트별 추적
```

### 2.3 효능 관리 (Efficacy System)

#### **herb_efficacy_tags** - 효능 태그 마스터
```sql
CREATE TABLE herb_efficacy_tags (
    tag_id INTEGER PRIMARY KEY,
    tag_name VARCHAR(50) UNIQUE,     -- "보혈", "활혈", "청열"
    tag_category VARCHAR(30),         -- "보익", "거사", "조리"
    description TEXT
)
-- 역할: 18개 표준 효능 태그 정의
```

#### **herb_item_tags** - 약재-태그 매핑 ⭐ 개선됨!
```sql
CREATE TABLE herb_item_tags (
    item_tag_id INTEGER PRIMARY KEY,
    ingredient_code VARCHAR(10),     -- 성분코드 직접 사용! (개선)
    tag_id INTEGER,
    strength INTEGER DEFAULT 3,      -- 효능 강도 (1-5)
    UNIQUE(ingredient_code, tag_id)
)
-- 이전: herb_id 사용 (복잡한 JOIN 필요)
-- 현재: ingredient_code 직접 사용 (간단!)
```

### 2.4 처방 및 조제 (Prescriptions & Compounding)

#### **formulas** - 처방 마스터
```sql
CREATE TABLE formulas (
    formula_id INTEGER PRIMARY KEY,
    formula_name VARCHAR(100),       -- "십전대보탕"
    formula_name_hanja VARCHAR(100), -- "十全大補湯"
    je_count INTEGER                 -- 기준 제수
)
```

#### **formula_ingredients** - 처방 구성
```sql
CREATE TABLE formula_ingredients (
    formula_id INTEGER,
    ingredient_code VARCHAR(10),     -- 성분코드 사용
    grams_per_cheop REAL            -- 첩당 용량
)
```

#### **compounds** - 조제 기록
```sql
CREATE TABLE compounds (
    compound_id INTEGER PRIMARY KEY,
    patient_id INTEGER,
    formula_id INTEGER,
    is_custom BOOLEAN,               -- 가감방 여부
    custom_details TEXT,             -- 가감 내용
    total_cost REAL,
    compound_date DATETIME
)
```

#### **compound_consumptions** - 소비 내역
```sql
CREATE TABLE compound_consumptions (
    compound_id INTEGER,
    herb_item_id INTEGER,
    lot_id INTEGER,
    quantity_used REAL,              -- 사용량(g)
    unit_cost_per_g REAL,
    cost_amount REAL
)
-- 특징: 복합 로트 지원 (한 약재에 여러 로트 사용 가능)
```

## 🔄 3. 데이터 흐름

### 3.1 입고 프로세스
```
1. Excel 업로드 (한의사랑 카탈로그)
   ↓
2. herb_products 매칭 (보험코드 기준)
   ↓
3. purchase_receipts 생성 (입고 헤더)
   ↓
4. purchase_receipt_lines 생성 (입고 상세)
   ↓
5. inventory_lots 생성 (로트별 재고)
   ↓
6. stock_ledger 기록 (재고 원장)
```

### 3.2 조제 프로세스
```
1. 처방 선택 (formulas)
   ↓
2. 구성 약재 로드 (formula_ingredients)
   ↓
3. 재고 매핑 (herb_items + inventory_lots)
   ↓
4. 가감 여부 확인 (원방 vs 현재 구성 비교)
   ↓
5. 로트 선택 (자동 FIFO 또는 수동 배분)
   ↓
6. compounds 생성 (조제 기록)
   ↓
7. compound_consumptions 생성 (소비 내역)
   ↓
8. inventory_lots 차감 (재고 감소)
   ↓
9. stock_ledger 기록 (원장 업데이트)
```

### 3.3 효능 태그 조회 (개선된 JOIN)

#### Before (복잡했던 구조):
```sql
-- 5단계 JOIN 필요
FROM herb_items h
LEFT JOIN herb_products hp ON h.insurance_code = hp.product_code
LEFT JOIN herb_masters hm ON hp.ingredient_code = hm.ingredient_code
LEFT JOIN herb_master_extended hme ON hm.ingredient_code = hme.ingredient_code
LEFT JOIN herb_item_tags hit ON hme.herb_id = hit.herb_id  -- herb_id 찾기
LEFT JOIN herb_efficacy_tags het ON hit.tag_id = het.tag_id
```

#### After (개선된 구조):
```sql
-- 3단계 JOIN으로 단순화!
FROM herb_items h
LEFT JOIN herb_products hp ON h.insurance_code = hp.product_code
LEFT JOIN herb_item_tags hit ON COALESCE(h.ingredient_code, hp.ingredient_code) = hit.ingredient_code
LEFT JOIN herb_efficacy_tags het ON hit.tag_id = het.tag_id
```

## 🎯 4. 핵심 매핑 관계

### 4.1 코드 체계 매핑
```
보험코드(9자리) → 성분코드(10자리)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
062400740      → 3007H1AHM (감초)
062403450      → 3105H1AHM (당귀)
A001300        → 3400H1AHM (인삼)

* herb_products 테이블이 중개 역할
```

### 4.2 재고 관계
```
herb_items (31개)
    ↓ 1:N
inventory_lots (여러 로트)
    ↓ 1:N
compound_consumptions (소비 기록)
```

### 4.3 처방 관계
```
formulas (처방)
    ↓ 1:N
formula_ingredients (구성 약재)
    ↓ ingredient_code
herb_masters (약재 마스터)
```

## 📈 5. 주요 통계 쿼리

### 5.1 재고 현황 요약
```sql
-- 주성분코드 기준 보유율
SELECT
    COUNT(DISTINCT m.ingredient_code) as 전체_약재,
    COUNT(DISTINCT CASE WHEN inv.total > 0 THEN m.ingredient_code END) as 보유_약재,
    ROUND(COUNT(DISTINCT CASE WHEN inv.total > 0 THEN m.ingredient_code END) * 100.0 /
          COUNT(DISTINCT m.ingredient_code), 1) as 보유율
FROM herb_masters m
LEFT JOIN (재고 서브쿼리) inv ON m.ingredient_code = inv.ingredient_code
```

### 5.2 효능별 약재 검색
```sql
-- 간단해진 쿼리!
SELECT DISTINCT h.*, GROUP_CONCAT(et.tag_name)
FROM herb_items h
LEFT JOIN herb_products hp ON h.insurance_code = hp.product_code
LEFT JOIN herb_item_tags hit ON COALESCE(h.ingredient_code, hp.ingredient_code) = hit.ingredient_code
LEFT JOIN herb_efficacy_tags et ON hit.tag_id = et.tag_id
WHERE et.tag_name IN ('보혈', '활혈')
GROUP BY h.herb_item_id
```

## 🚀 6. 최근 개선사항 (2026-02-17)

### 6.1 효능 태그 시스템 리팩토링
- **문제**: `herb_id`를 통한 복잡한 JOIN
- **해결**: `ingredient_code` 직접 사용
- **효과**: JOIN 단계 5개 → 3개로 감소

### 6.2 가감방 감지 시스템
- **구현**: 실시간 처방 변경 감지
- **방식**: `ingredient_code` 기준 비교
- **UI**: 가감방 배지 자동 표시

### 6.3 복합 로트 시스템
- **기능**: 한 약재에 여러 로트 사용 가능
- **UI**: 수동 로트 배분 모달
- **검증**: 재고량 실시간 체크

## 📝 7. 주의사항

### 7.1 ID 체계 혼동 주의
```
⚠️ herb_item_id ≠ herb_id
- herb_item_id: herb_items의 PK (재고 관리)
- herb_id: herb_master_extended의 PK (단순 인덱스)
- 실제 KEY: ingredient_code (성분코드)
```

### 7.2 코드 매핑 순서
```
1. 보험코드로 입력받음 (9자리)
2. herb_products에서 ingredient_code 찾기
3. ingredient_code로 모든 정보 연결
```

### 7.3 재고 없는 약재 처리
```
- herb_items에 없어도 herb_masters에는 존재
- 효능 정보는 ingredient_code 기준
- UI에서 재고 0으로 표시
```

## 🔧 8. 개발 가이드

### 8.1 새 약재 추가 시
```python
# 1. herb_masters에 성분코드 확인
# 2. herb_products에 보험코드 매핑 추가
# 3. herb_items에 재고 단위 생성
# 4. 입고 처리로 inventory_lots 생성
```

### 8.2 효능 태그 추가 시
```python
# 간단해진 방식!
INSERT INTO herb_item_tags (ingredient_code, tag_id, strength)
VALUES ('3400H1AHM', 1, 5)  -- 인삼에 보기(5) 추가
```

### 8.3 API 개발 시
```python
# 항상 ingredient_code 중심으로 JOIN
# herb_products 테이블 활용
# COALESCE로 안전하게 처리
```

## 📚 9. 관련 문서

- [조제 프로세스 및 커스텀 처방](./조제_프로세스_및_커스텀_처방.md)
- [복합 로트 사용 분석](./복합_로트_사용_분석.md)
- [한약재 정보 관리 시스템 설계](./한약재_정보_관리_시스템_설계.md)

---

*이 문서는 시스템의 핵심 데이터 구조와 흐름을 설명합니다.*
*질문이나 수정사항은 개발팀에 문의해주세요.*