docs: 데이터베이스 스키마 및 API 문서 추가

- database_schema.md: 전체 테이블 구조 상세 설명
  - 27개 테이블의 컬럼 정의 및 설명
  - 테이블 간 관계 설명
  - 주요 비즈니스 규칙 문서화

- database_erd.md: ER 다이어그램 및 데이터 플로우
  - Mermaid 다이어그램으로 시각화
  - 재고 흐름도, 처방-조제 흐름 설명
  - 인덱스 전략 및 데이터 무결성 규칙

- api_documentation.md: REST API 상세 명세
  - 약재, 처방, 조제, 재고, 환자 관리 API
  - 요청/응답 형식 예시
  - 에러 처리 방식

- README 업데이트: 문서 링크 추가

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
시골약사 2026-02-15 19:07:34 +00:00
parent 0bf0772864
commit 116712aa24
4 changed files with 1214 additions and 2 deletions

View File

@ -53,24 +53,33 @@
## 데이터베이스 구조 ## 데이터베이스 구조
### 핵심 테이블 ### 핵심 테이블
- `herb_masters` - 약재 마스터 (성분코드 기준, 454개 표준 약재)
- `herb_items` - 약재 제품 (제조사별 개별 제품)
- `patients` - 환자 정보 - `patients` - 환자 정보
- `herb_items` - 약재 마스터 (보험코드 기준)
- `suppliers` - 도매상 정보 - `suppliers` - 도매상 정보
- `purchase_receipts` - 입고장 헤더 - `purchase_receipts` - 입고장 헤더
- `purchase_receipt_lines` - 입고장 상세 - `purchase_receipt_lines` - 입고장 상세
- `inventory_lots` - 로트별 재고 - `inventory_lots` - 로트별 재고
- `formulas` - 처방 마스터 - `formulas` - 처방 마스터
- `formula_ingredients` - 처방 구성 약재 - `formula_ingredients` - 처방 구성 약재 (ingredient_code 기반)
- `compounds` - 조제 작업 - `compounds` - 조제 작업
- `compound_consumptions` - 로트별 차감 내역 - `compound_consumptions` - 로트별 차감 내역
- `stock_ledger` - 재고 원장 (모든 변동 기록) - `stock_ledger` - 재고 원장 (모든 변동 기록)
### 핵심 개념 ### 핵심 개념
- **성분코드 (ingredient_code)**: 표준 약재 식별자
- **2단계 약재 체계**: 마스터(성분) → 제품(제조사별)
- **1제 = 20첩 = 30파우치** (기본값, 조정 가능) - **1제 = 20첩 = 30파우치** (기본값, 조정 가능)
- **로트 관리**: 입고 시점별로 재고를 구분 관리 - **로트 관리**: 입고 시점별로 재고를 구분 관리
- **FIFO 차감**: 오래된 재고부터 우선 사용 - **FIFO 차감**: 오래된 재고부터 우선 사용
- **원가 추적**: 로트별 단가 기준 정확한 원가 계산 - **원가 추적**: 로트별 단가 기준 정확한 원가 계산
## 📚 문서
- [데이터베이스 스키마](docs/database_schema.md) - 전체 테이블 구조 상세 설명
- [ER 다이어그램](docs/database_erd.md) - 엔티티 관계도 및 데이터 플로우
- [API 문서](docs/api_documentation.md) - REST API 엔드포인트 상세 명세
## 설치 방법 ## 설치 방법
### 1. 필수 요구사항 ### 1. 필수 요구사항

553
docs/api_documentation.md Normal file
View File

@ -0,0 +1,553 @@
# 한의원 약재 관리 시스템 API 문서
## 목차
1. [약재 관리 API](#약재-관리-api)
2. [처방 관리 API](#처방-관리-api)
3. [조제 관리 API](#조제-관리-api)
4. [재고 관리 API](#재고-관리-api)
5. [환자 관리 API](#환자-관리-api)
6. [구매/입고 API](#구매입고-api)
7. [재고 조정 API](#재고-조정-api)
## 약재 관리 API
### GET /api/herbs
약재 제품 목록 조회
**Response:**
```json
{
"success": true,
"data": [
{
"herb_item_id": 1,
"insurance_code": "A001300",
"herb_name": "인삼",
"stock_quantity": 1500.0,
"efficacy_tags": ["보기", "생진"]
}
]
}
```
### GET /api/herbs/masters
마스터 약재 목록 조회 (454개 표준 약재)
**Response:**
```json
{
"success": true,
"data": [
{
"ingredient_code": "3400H1AHM",
"herb_name": "인삼",
"herb_name_hanja": "人蔘",
"herb_name_latin": "Ginseng Radix",
"stock_quantity": 7000.0,
"has_stock": 1,
"lot_count": 3,
"product_count": 2,
"company_count": 2,
"efficacy_tags": ["보기", "생진"]
}
]
}
```
### GET /api/herbs/by-ingredient/{ingredient_code}
특정 성분코드의 제품 목록 조회
**Parameters:**
- `ingredient_code`: 성분코드 (예: 3400H1AHM)
**Response:**
```json
{
"success": true,
"data": [
{
"herb_item_id": 38,
"insurance_code": "060600420",
"herb_name": "인삼",
"product_name": "신흥인삼",
"company_name": "신흥",
"specification": "(주)신흥제약",
"stock_quantity": 7000.0,
"lot_count": 2,
"avg_price": 17.5
}
]
}
```
### GET /api/herbs/{herb_item_id}/available-lots
조제용 가용 로트 목록 (원산지별 그룹화)
**Parameters:**
- `herb_item_id`: 제품 ID
**Response:**
```json
{
"success": true,
"data": {
"herb_name": "인삼",
"insurance_code": "060600420",
"origins": [
{
"origin_country": "한국",
"total_quantity": 3000.0,
"min_price": 20.0,
"max_price": 25.0,
"lot_count": 2,
"lots": [
{
"lot_id": 1,
"quantity_onhand": 1500.0,
"unit_price_per_g": 20.0,
"received_date": "2024-01-15"
}
]
}
],
"total_quantity": 7000.0
}
}
```
## 처방 관리 API
### GET /api/formulas
처방 목록 조회
**Response:**
```json
{
"success": true,
"data": [
{
"formula_id": 1,
"formula_code": "F001",
"formula_name": "쌍화탕",
"formula_type": "탕제",
"base_cheop": 20,
"base_pouches": 60
}
]
}
```
### POST /api/formulas
처방 등록
**Request Body:**
```json
{
"formula_code": "F002",
"formula_name": "십전대보탕",
"formula_type": "탕제",
"base_cheop": 20,
"base_pouches": 60,
"description": "기혈 보충",
"ingredients": [
{
"ingredient_code": "3400H1AHM",
"grams_per_cheop": 6.0,
"notes": ""
}
]
}
```
### GET /api/formulas/{formula_id}/ingredients
처방 구성 약재 조회 (ingredient_code 기반)
**Response:**
```json
{
"success": true,
"data": [
{
"ingredient_code": "3400H1AHM",
"herb_name": "인삼",
"grams_per_cheop": 6.0,
"total_available_stock": 7000.0,
"available_products": [
{
"herb_item_id": 38,
"herb_name": "신흥인삼",
"specification": "(주)신흥제약",
"stock": 7000.0
}
]
}
]
}
```
## 조제 관리 API
### POST /api/compounds
조제 실행
**Request Body:**
```json
{
"patient_id": 1,
"formula_id": 1,
"je_count": 1,
"cheop_total": 20,
"pouch_total": 60,
"ingredients": [
{
"herb_item_id": 38,
"grams_per_cheop": 6.0,
"origin": "auto"
}
]
}
```
**Response:**
```json
{
"success": true,
"compound_id": 123,
"message": "조제가 완료되었습니다",
"summary": {
"total_cost": 15000,
"consumptions": [
{
"herb_name": "인삼",
"total_used": 120.0,
"lots_used": [
{
"lot_id": 1,
"origin": "한국",
"quantity": 120.0,
"unit_price": 20.0
}
]
}
]
}
}
```
### GET /api/compounds/recent
최근 조제 내역
**Query Parameters:**
- `limit`: 조회 건수 (기본값: 10)
- `patient_id`: 환자 ID (선택)
**Response:**
```json
{
"success": true,
"data": [
{
"compound_id": 123,
"compound_date": "2024-01-20",
"patient_name": "홍길동",
"formula_name": "쌍화탕",
"cheop_total": 20,
"pouch_total": 60,
"cost_total": 15000,
"status": "completed"
}
]
}
```
## 재고 관리 API
### GET /api/inventory/summary
재고 현황 요약
**Response:**
```json
{
"success": true,
"data": {
"total_items": 87,
"items_with_stock": 75,
"total_value": 2500000,
"by_origin": {
"한국": {
"item_count": 30,
"total_quantity": 15000,
"total_value": 1200000
},
"중국": {
"item_count": 45,
"total_quantity": 25000,
"total_value": 1300000
}
}
}
}
```
### GET /api/inventory/low-stock
재고 부족 약재 조회
**Query Parameters:**
- `threshold`: 재고 기준량 (기본값: 100g)
**Response:**
```json
{
"success": true,
"data": [
{
"herb_item_id": 5,
"herb_name": "당귀",
"current_stock": 50.0,
"threshold": 100.0,
"last_purchase_date": "2024-01-01"
}
]
}
```
### GET /api/stock-ledger
재고 원장 조회
**Query Parameters:**
- `herb_item_id`: 제품 ID (선택)
- `start_date`: 시작일 (선택)
- `end_date`: 종료일 (선택)
- `event_type`: IN/OUT/ADJUST (선택)
**Response:**
```json
{
"success": true,
"data": [
{
"ledger_id": 1,
"event_time": "2024-01-20 14:30:00",
"event_type": "OUT",
"herb_name": "인삼",
"lot_id": 1,
"quantity_delta": -120.0,
"reference_table": "compound_consumptions",
"reference_id": 456
}
]
}
```
## 환자 관리 API
### GET /api/patients
환자 목록 조회
**Query Parameters:**
- `search`: 검색어 (이름, 전화번호)
- `is_active`: 활성 여부
**Response:**
```json
{
"success": true,
"data": [
{
"patient_id": 1,
"name": "홍길동",
"phone": "010-1234-5678",
"gender": "M",
"birth_date": "1980-01-01",
"last_visit": "2024-01-20"
}
]
}
```
### POST /api/patients
환자 등록
**Request Body:**
```json
{
"name": "홍길동",
"phone": "010-1234-5678",
"jumin_no": "800101-1******",
"gender": "M",
"birth_date": "1980-01-01",
"address": "서울시 강남구",
"notes": ""
}
```
### GET /api/patients/{patient_id}/prescriptions
환자 처방 이력
**Response:**
```json
{
"success": true,
"data": [
{
"compound_id": 123,
"compound_date": "2024-01-20",
"formula_name": "쌍화탕",
"cheop_total": 20,
"pouch_total": 60,
"cost_total": 15000,
"ingredients": [
{
"herb_name": "인삼",
"product_name": "신흥인삼",
"grams_per_cheop": 6.0,
"total_grams": 120.0,
"origin_country": "한국"
}
]
}
]
}
```
## 구매/입고 API
### POST /api/purchases/upload
거래명세표 업로드
**Form Data:**
- `file`: 엑셀 파일
- `supplier_id`: 공급처 ID
**Response:**
```json
{
"success": true,
"receipt_id": 789,
"summary": {
"total_items": 25,
"total_amount": 500000,
"items_processed": 25,
"items_failed": 0
}
}
```
### POST /api/purchases/receipts
구매 영수증 등록
**Request Body:**
```json
{
"supplier_id": 1,
"receipt_date": "2024-01-20",
"receipt_no": "R2024012001",
"vat_included": true,
"vat_rate": 10.0,
"total_amount": 550000,
"lines": [
{
"herb_item_id": 38,
"origin_country": "한국",
"quantity_g": 1000,
"unit_price_per_g": 20.0,
"line_total": 20000
}
]
}
```
## 재고 조정 API
### POST /api/stock-adjustments
재고 보정
**Request Body:**
```json
{
"adjustment_date": "2024-01-20",
"adjustment_type": "correction",
"notes": "실사 보정",
"details": [
{
"herb_item_id": 38,
"lot_id": 1,
"quantity_after": 1480.0,
"reason": "실사 차이"
}
]
}
```
### GET /api/stock-adjustments
재고 보정 내역 조회
**Query Parameters:**
- `start_date`: 시작일
- `end_date`: 종료일
- `herb_item_id`: 제품 ID (선택)
**Response:**
```json
{
"success": true,
"data": [
{
"adjustment_id": 1,
"adjustment_date": "2024-01-20",
"adjustment_no": "ADJ20240120001",
"adjustment_type": "correction",
"total_items": 5,
"created_by": "admin"
}
]
}
```
## 통계 API
### GET /api/stats/herb-usage
약재 사용 통계
**Query Parameters:**
- `period`: daily/weekly/monthly
- `start_date`: 시작일
- `end_date`: 종료일
**Response:**
```json
{
"success": true,
"data": {
"period": "2024-01",
"top_used": [
{
"herb_name": "인삼",
"total_quantity": 5000.0,
"usage_count": 25,
"total_cost": 100000
}
],
"total_compounds": 150,
"total_cost": 3000000
}
}
```
## 에러 응답
모든 API는 다음과 같은 에러 응답 형식을 따릅니다:
```json
{
"success": false,
"error": "에러 메시지",
"code": "ERROR_CODE"
}
```
### HTTP 상태 코드
- `200 OK`: 성공
- `400 Bad Request`: 잘못된 요청
- `404 Not Found`: 리소스를 찾을 수 없음
- `500 Internal Server Error`: 서버 오류

252
docs/database_erd.md Normal file
View File

@ -0,0 +1,252 @@
# 한의원 약재 관리 시스템 ER 다이어그램
## 핵심 엔티티 관계도
```mermaid
erDiagram
HERB_MASTERS ||--o{ HERB_ITEMS : "has"
HERB_MASTERS ||--o{ FORMULA_INGREDIENTS : "used_in"
HERB_ITEMS ||--o{ INVENTORY_LOTS : "has"
HERB_ITEMS ||--o{ COMPOUND_INGREDIENTS : "used_in"
HERB_ITEMS ||--o{ HERB_ITEM_TAGS : "has"
HERB_EFFICACY_TAGS ||--o{ HERB_ITEM_TAGS : "assigned_to"
FORMULAS ||--o{ FORMULA_INGREDIENTS : "contains"
FORMULAS ||--o{ COMPOUNDS : "used_for"
PATIENTS ||--o{ COMPOUNDS : "receives"
PATIENTS ||--o{ PATIENT_SURVEYS : "completes"
COMPOUNDS ||--o{ COMPOUND_INGREDIENTS : "contains"
COMPOUND_INGREDIENTS ||--o{ COMPOUND_CONSUMPTIONS : "consumes"
INVENTORY_LOTS ||--o{ COMPOUND_CONSUMPTIONS : "consumed_by"
INVENTORY_LOTS }o--|| SUPPLIERS : "supplied_by"
INVENTORY_LOTS }o--|| PURCHASE_RECEIPT_LINES : "received_from"
SUPPLIERS ||--o{ PURCHASE_RECEIPTS : "provides"
PURCHASE_RECEIPTS ||--o{ PURCHASE_RECEIPT_LINES : "contains"
STOCK_ADJUSTMENTS ||--o{ STOCK_ADJUSTMENT_DETAILS : "contains"
STOCK_LEDGER }o--|| HERB_ITEMS : "tracks"
STOCK_LEDGER }o--|| INVENTORY_LOTS : "tracks"
HERB_MASTERS {
string ingredient_code PK
string herb_name
string herb_name_hanja
string herb_name_latin
text description
boolean is_active
}
HERB_ITEMS {
int herb_item_id PK
string ingredient_code FK
string insurance_code
string herb_name
string specification
boolean is_active
}
INVENTORY_LOTS {
int lot_id PK
int herb_item_id FK
int supplier_id FK
date received_date
string origin_country
decimal unit_price_per_g
decimal quantity_onhand
date expiry_date
boolean is_depleted
}
FORMULAS {
int formula_id PK
string formula_code
string formula_name
string formula_type
int base_cheop
int base_pouches
boolean is_active
}
FORMULA_INGREDIENTS {
int ingredient_id PK
int formula_id FK
string ingredient_code FK
decimal grams_per_cheop
int sort_order
}
COMPOUNDS {
int compound_id PK
int patient_id FK
int formula_id FK
date compound_date
decimal cheop_total
decimal pouch_total
decimal cost_total
string status
}
PATIENTS {
int patient_id PK
string name
string phone
string gender
date birth_date
boolean is_active
}
```
## 재고 흐름도
```mermaid
flowchart TB
subgraph 입고
S[공급처/Suppliers]
PR[구매영수증/Purchase Receipts]
PRL[구매영수증라인/Purchase Receipt Lines]
S --> PR
PR --> PRL
end
subgraph 재고
HM[약재마스터/Herb Masters]
HI[약재제품/Herb Items]
IL[재고로트/Inventory Lots]
SL[재고원장/Stock Ledger]
HM --> HI
HI --> IL
PRL --> IL
IL -.-> SL
end
subgraph 조제/출고
F[처방/Formulas]
FI[처방구성/Formula Ingredients]
C[조제/Compounds]
CI[조제구성/Compound Ingredients]
CC[조제소비/Compound Consumptions]
F --> FI
FI -.->|ingredient_code| HM
F --> C
C --> CI
CI --> CC
CC --> IL
end
subgraph 재고조정
SA[재고조정/Stock Adjustments]
SAD[조정상세/Adjustment Details]
SA --> SAD
SAD --> IL
end
IL --> SL
CC --> SL
SAD --> SL
classDef master fill:#e1f5fe
classDef transaction fill:#fff3e0
classDef inventory fill:#f3e5f5
classDef ledger fill:#e8f5e9
class HM,HI,F master
class PR,PRL,C,CI,CC transaction
class IL inventory
class SL,SA,SAD ledger
```
## 데이터 플로우
### 1. 약재 마스터 데이터 흐름
```
herb_masters (성분코드)
herb_items (제품별 재고 단위)
inventory_lots (로트별 실재고)
```
### 2. 처방 → 조제 흐름
```
formulas (처방 마스터)
formula_ingredients (ingredient_code 기반)
compounds (실제 조제)
compound_ingredients (제품 선택)
compound_consumptions (로트별 소비)
```
### 3. 구매 → 재고 흐름
```
suppliers (공급처)
purchase_receipts (영수증)
purchase_receipt_lines (라인)
inventory_lots (재고 생성)
stock_ledger (원장 기록)
```
## 주요 비즈니스 규칙
### 재고 관리
1. **FIFO (선입선출)**: 오래된 로트부터 자동 소비
2. **로트 추적**: 모든 재고는 lot_id로 추적
3. **원산지 관리**: 로트별 origin_country 관리
4. **가격 추적**: 로트별 unit_price_per_g 관리
### 처방 관리
1. **성분코드 기반**: formula_ingredients는 ingredient_code 사용
2. **유연한 제품 선택**: 동일 성분의 다른 제품 선택 가능
3. **2단계 선택**: 약재(마스터) → 제품 → 로트
### 조제 관리
1. **처방 조제**: 등록된 처방 사용
2. **직접 조제**: 처방 없이 직접 구성
3. **가감 가능**: 처방 기본 구성에서 추가/제거 가능
### 원가 계산
```
조제 원가 = Σ(사용량 × 로트별 단가)
```
## 인덱스 전략
### 주요 인덱스
- `herb_items.ingredient_code`: 성분코드 조회
- `inventory_lots.herb_item_id, is_depleted`: 가용 재고 조회
- `inventory_lots.origin_country`: 원산지별 재고 조회
- `formula_ingredients.formula_id`: 처방 구성 조회
- `compounds.patient_id, compound_date`: 환자 조제 이력
- `stock_ledger.herb_item_id, event_time`: 재고 변동 이력
## 데이터 무결성
### 외래키 제약
- `herb_items.ingredient_code``herb_masters.ingredient_code`
- `formula_ingredients.ingredient_code``herb_masters.ingredient_code`
- `inventory_lots.herb_item_id``herb_items.herb_item_id`
- `compound_ingredients.herb_item_id``herb_items.herb_item_id`
- `compound_consumptions.lot_id``inventory_lots.lot_id`
### 체크 제약
- `inventory_lots.quantity_onhand >= 0`
- `compound_consumptions.quantity_used > 0`
- `purchase_receipt_lines.quantity_g > 0`
- `formula_ingredients.grams_per_cheop > 0`
### 트리거
- 재고 변동 시 `stock_ledger` 자동 기록
- `inventory_lots.quantity_onhand = 0``is_depleted = 1` 자동 설정

398
docs/database_schema.md Normal file
View File

@ -0,0 +1,398 @@
# 한의원 약재 관리 시스템 데이터베이스 스키마
## 목차
1. [핵심 마스터 테이블](#핵심-마스터-테이블)
2. [재고 관리 테이블](#재고-관리-테이블)
3. [조제 관리 테이블](#조제-관리-테이블)
4. [구매/입고 관리 테이블](#구매입고-관리-테이블)
5. [환자 관리 테이블](#환자-관리-테이블)
6. [재고 조정 테이블](#재고-조정-테이블)
7. [설문 관리 테이블](#설문-관리-테이블)
## 핵심 마스터 테이블
### herb_masters (약재 마스터)
통합 약재 마스터 정보. 성분코드(ingredient_code) 기준 관리.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| ingredient_code | VARCHAR(10) PK | 성분코드 (예: 3400H1AHM) |
| herb_name | VARCHAR(100) | 한글명 (예: 인삼) |
| herb_name_hanja | VARCHAR(100) | 한자명 (예: 人蔘) |
| herb_name_latin | VARCHAR(200) | 라틴명 |
| description | TEXT | 설명 |
| is_active | BOOLEAN | 사용 여부 |
| created_at | TIMESTAMP | 생성일시 |
| updated_at | TIMESTAMP | 수정일시 |
### herb_items (약재 제품)
실제 재고 관리 단위. 제조사별 개별 제품.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| herb_item_id | INTEGER PK | 제품 ID |
| ingredient_code | VARCHAR(10) FK | 성분코드 (herb_masters 참조) |
| insurance_code | TEXT | 보험코드 |
| herb_name | TEXT | 제품명 (예: 신흥인삼) |
| specification | TEXT | 규격/제조사 (예: (주)신흥제약) |
| default_unit | TEXT | 기본 단위 |
| is_active | INTEGER | 사용 여부 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### herb_products (표준 약재 제품 목록)
건강보험 표준 약재 제품 목록.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| product_id | INTEGER PK | 제품 ID |
| ingredient_code | VARCHAR(10) FK | 성분코드 |
| product_code | VARCHAR(9) | 제품코드 |
| company_name | VARCHAR(200) | 제조사명 |
| product_name | VARCHAR(200) | 제품명 |
| standard_code | VARCHAR(20) | 표준코드 |
| representative_code | VARCHAR(20) | 대표코드 |
| package_size | VARCHAR(20) | 포장 크기 |
| package_unit | VARCHAR(20) | 포장 단위 |
| valid_from | DATE | 유효 시작일 |
| valid_to | DATE | 유효 종료일 |
| is_active | BOOLEAN | 사용 여부 |
### formulas (처방 마스터)
등록된 처방 정보.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| formula_id | INTEGER PK | 처방 ID |
| formula_code | TEXT | 처방코드 |
| formula_name | TEXT | 처방명 (예: 쌍화탕) |
| formula_type | TEXT | 처방 유형 |
| base_cheop | INTEGER | 기본 첩수 |
| base_pouches | INTEGER | 기본 포수 |
| description | TEXT | 설명 |
| is_active | INTEGER | 사용 여부 |
| created_by | TEXT | 생성자 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### formula_ingredients (처방 구성)
처방별 구성 약재. **ingredient_code 기반**.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| ingredient_id | INTEGER PK | 구성 ID |
| formula_id | INTEGER FK | 처방 ID |
| ingredient_code | TEXT | 성분코드 (herb_masters 참조) |
| grams_per_cheop | REAL | 1첩당 용량(g) |
| notes | TEXT | 비고 |
| sort_order | INTEGER | 정렬 순서 |
| created_at | DATETIME | 생성일시 |
## 재고 관리 테이블
### inventory_lots (재고 로트)
로트별 재고 관리.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| lot_id | INTEGER PK | 로트 ID |
| herb_item_id | INTEGER FK | 제품 ID |
| supplier_id | INTEGER FK | 공급처 ID |
| receipt_line_id | INTEGER FK | 입고 라인 ID |
| received_date | DATE | 입고일 |
| origin_country | TEXT | 원산지 (예: 중국, 한국) |
| unit_price_per_g | REAL | g당 단가 |
| quantity_received | REAL | 입고량(g) |
| quantity_onhand | REAL | 현재고량(g) |
| expiry_date | DATE | 유효기간 |
| lot_number | TEXT | 로트번호 |
| is_depleted | INTEGER | 소진 여부 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### stock_ledger (재고 원장)
모든 재고 변동 이력 관리.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| ledger_id | INTEGER PK | 원장 ID |
| event_time | DATETIME | 이벤트 시간 |
| event_type | TEXT | 이벤트 유형 (IN/OUT/ADJUST) |
| herb_item_id | INTEGER FK | 제품 ID |
| lot_id | INTEGER FK | 로트 ID |
| quantity_delta | REAL | 수량 변동 (+/-) |
| unit_cost_per_g | REAL | g당 단가 |
| reference_table | TEXT | 참조 테이블명 |
| reference_id | INTEGER | 참조 ID |
| notes | TEXT | 비고 |
| created_by | TEXT | 생성자 |
| created_at | DATETIME | 생성일시 |
## 조제 관리 테이블
### compounds (조제 내역)
환자별 조제 내역.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| compound_id | INTEGER PK | 조제 ID |
| patient_id | INTEGER FK | 환자 ID |
| formula_id | INTEGER FK | 처방 ID (NULL 가능 - 직접조제) |
| compound_date | DATE | 조제일 |
| je_count | REAL | 제수 |
| cheop_total | REAL | 총 첩수 |
| pouch_total | REAL | 총 포수 |
| cost_total | REAL | 원가 합계 |
| sell_price_total | REAL | 판매가 합계 |
| prescription_no | TEXT | 처방전 번호 |
| status | TEXT | 상태 |
| notes | TEXT | 비고 |
| created_by | TEXT | 생성자 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### compound_ingredients (조제 구성 약재)
조제별 사용 약재 구성.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| compound_ingredient_id | INTEGER PK | 구성 ID |
| compound_id | INTEGER FK | 조제 ID |
| herb_item_id | INTEGER FK | 제품 ID |
| grams_per_cheop | REAL | 1첩당 용량(g) |
| total_grams | REAL | 총 용량(g) |
| notes | TEXT | 비고 |
| created_at | DATETIME | 생성일시 |
### compound_consumptions (조제 소비 내역)
조제 시 실제 소비한 재고 로트별 내역.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| consumption_id | INTEGER PK | 소비 ID |
| compound_id | INTEGER FK | 조제 ID |
| herb_item_id | INTEGER FK | 제품 ID |
| lot_id | INTEGER FK | 로트 ID |
| quantity_used | REAL | 사용량(g) |
| unit_cost_per_g | REAL | g당 단가 |
| cost_amount | REAL | 원가 금액 |
| created_at | DATETIME | 생성일시 |
## 구매/입고 관리 테이블
### suppliers (공급처)
약재 공급처 정보.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| supplier_id | INTEGER PK | 공급처 ID |
| name | TEXT | 공급처명 |
| business_no | TEXT | 사업자번호 |
| contact_person | TEXT | 담당자 |
| phone | TEXT | 전화번호 |
| address | TEXT | 주소 |
| is_active | INTEGER | 사용 여부 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### purchase_receipts (구매 영수증)
구매/입고 영수증 헤더.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| receipt_id | INTEGER PK | 영수증 ID |
| supplier_id | INTEGER FK | 공급처 ID |
| receipt_date | DATE | 거래일 |
| receipt_no | TEXT | 영수증 번호 |
| vat_included | INTEGER | VAT 포함 여부 |
| vat_rate | REAL | VAT 비율 |
| total_amount | REAL | 총 금액 |
| source_file | TEXT | 원본 파일 |
| notes | TEXT | 비고 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### purchase_receipt_lines (구매 영수증 라인)
구매/입고 영수증 상세 라인.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| line_id | INTEGER PK | 라인 ID |
| receipt_id | INTEGER FK | 영수증 ID |
| herb_item_id | INTEGER FK | 제품 ID |
| origin_country | TEXT | 원산지 |
| quantity_g | REAL | 수량(g) |
| unit_price_per_g | REAL | g당 단가 |
| line_total | REAL | 라인 합계 |
| expiry_date | DATE | 유효기간 |
| lot_number | TEXT | 로트번호 |
| created_at | DATETIME | 생성일시 |
## 환자 관리 테이블
### patients (환자)
환자 기본 정보.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| patient_id | INTEGER PK | 환자 ID |
| name | TEXT | 환자명 |
| phone | TEXT | 전화번호 |
| jumin_no | TEXT | 주민번호 |
| gender | TEXT | 성별 |
| birth_date | DATE | 생년월일 |
| address | TEXT | 주소 |
| notes | TEXT | 비고 |
| is_active | INTEGER | 사용 여부 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
## 재고 조정 테이블
### stock_adjustments (재고 조정)
재고 보정 헤더.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| adjustment_id | INTEGER PK | 조정 ID |
| adjustment_date | DATE | 조정일 |
| adjustment_no | TEXT | 조정 번호 |
| adjustment_type | TEXT | 조정 유형 |
| notes | TEXT | 비고 |
| created_by | TEXT | 생성자 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### stock_adjustment_details (재고 조정 상세)
재고 보정 상세 내역.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| detail_id | INTEGER PK | 상세 ID |
| adjustment_id | INTEGER FK | 조정 ID |
| herb_item_id | INTEGER FK | 제품 ID |
| lot_id | INTEGER FK | 로트 ID |
| quantity_before | REAL | 조정 전 수량 |
| quantity_after | REAL | 조정 후 수량 |
| quantity_delta | REAL | 조정량 |
| reason | TEXT | 사유 |
| created_at | DATETIME | 생성일시 |
## 효능 태그 테이블
### herb_efficacy_tags (효능 태그)
약재 효능 마스터.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| tag_id | INTEGER PK | 태그 ID |
| tag_name | VARCHAR(50) | 태그명 (예: 보혈, 활혈) |
| tag_category | VARCHAR(50) | 카테고리 |
| description | TEXT | 설명 |
| created_at | TIMESTAMP | 생성일시 |
### herb_item_tags (약재-태그 연결)
약재와 효능 태그 다대다 관계.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| herb_item_id | INTEGER FK | 제품 ID |
| tag_id | INTEGER FK | 태그 ID |
## 설문 관리 테이블
### survey_templates (설문 템플릿)
설문 질문 템플릿.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| template_id | INTEGER PK | 템플릿 ID |
| category | TEXT | 카테고리 |
| category_name | TEXT | 카테고리명 |
| question_code | TEXT | 질문 코드 |
| question_text | TEXT | 질문 내용 |
| question_subtext | TEXT | 보조 설명 |
| input_type | TEXT | 입력 타입 |
| options | TEXT | 선택 옵션 |
| is_required | INTEGER | 필수 여부 |
| sort_order | INTEGER | 정렬 순서 |
| is_active | INTEGER | 사용 여부 |
| created_at | DATETIME | 생성일시 |
### patient_surveys (환자 설문)
환자별 설문 내역.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| survey_id | INTEGER PK | 설문 ID |
| patient_id | INTEGER FK | 환자 ID |
| survey_token | TEXT | 설문 토큰 |
| survey_date | DATE | 설문일 |
| status | TEXT | 상태 |
| created_at | DATETIME | 생성일시 |
| completed_at | DATETIME | 완료일시 |
| reviewed_at | DATETIME | 검토일시 |
| reviewed_by | TEXT | 검토자 |
| notes | TEXT | 비고 |
### survey_responses (설문 응답)
설문 응답 내역.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| response_id | INTEGER PK | 응답 ID |
| survey_id | INTEGER FK | 설문 ID |
| category | TEXT | 카테고리 |
| question_code | TEXT | 질문 코드 |
| question_text | TEXT | 질문 내용 |
| answer_value | TEXT | 응답 값 |
| answer_type | TEXT | 응답 타입 |
| created_at | DATETIME | 생성일시 |
| updated_at | DATETIME | 수정일시 |
### survey_progress (설문 진행 상태)
설문 카테고리별 진행 상태.
| 컬럼명 | 타입 | 설명 |
|--------|------|------|
| progress_id | INTEGER PK | 진행 ID |
| survey_id | INTEGER FK | 설문 ID |
| category | TEXT | 카테고리 |
| total_questions | INTEGER | 전체 질문 수 |
| answered_questions | INTEGER | 응답 질문 수 |
| is_completed | INTEGER | 완료 여부 |
| last_updated | DATETIME | 최종 수정일시 |
## 주요 관계
1. **약재 계층 구조**
- `herb_masters` (마스터) ← `herb_items` (제품) ← `inventory_lots` (로트)
- ingredient_code로 연결
2. **처방-조제 관계**
- `formulas``formula_ingredients` (ingredient_code 기반)
- `compounds``compound_ingredients``compound_consumptions`
3. **재고 추적**
- 입고: `purchase_receipts``purchase_receipt_lines``inventory_lots`
- 출고: `compound_consumptions``inventory_lots`
- 이력: 모든 변동은 `stock_ledger`에 기록
4. **가격 정책**
- FIFO (선입선출) 기준
- lot별 unit_price_per_g 관리
## 마이그레이션 이력
### 2024년 주요 변경사항
1. `formula_ingredients` 테이블: `herb_item_id``ingredient_code` 변경
- 특정 제품이 아닌 성분코드 기준 처방 구성
- 조제 시 동일 성분의 다른 제품 선택 가능
2. `herb_masters` 테이블 추가
- 454개 표준 약재 마스터 데이터
- ingredient_code 기준 통합 관리
3. `herb_efficacy_tags` 시스템 추가
- 18개 기본 효능 태그
- 약재별 효능 분류 체계