# 한약 재고관리 시스템 데이터 구조 및 흐름 > 최종 수정: 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) --- *이 문서는 시스템의 핵심 데이터 구조와 흐름을 설명합니다.* *질문이나 수정사항은 개발팀에 문의해주세요.*