docs: 프로젝트 분석 및 개선 방안 문서 추가
추가된 문서: 1. 프로젝트_전체_분석.md - 시스템 아키텍처 분석 - 디렉토리 구조 정리 - 데이터베이스 설계 상세 - 주요 기능 및 비즈니스 로직 2. 보험코드_매핑_문제_분석.md - Excel 입고 시 보험코드 처리 문제 분석 - 앞자리 0 누락 문제 원인과 해결방안 - 영향 범위 및 수정 방법 3. 입고_프로세스_개선방안.md - 성분코드-보험코드 매핑 구조 설명 - 개선된 입고 프로세스 설계 - 성분코드 기준 재고 관리 방법 - 구현 우선순위 및 기대 효과 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
849c2dd561
commit
f367781031
128
docs/보험코드_매핑_문제_분석.md
Normal file
128
docs/보험코드_매핑_문제_분석.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Excel 입고 시 보험코드 매핑 문제 분석
|
||||
|
||||
## 현상
|
||||
Excel 파일에서 입고 처리 시, 보험코드가 제대로 매핑되지 않는 문제 발생
|
||||
|
||||
## 문제 원인
|
||||
|
||||
### 1. 보험코드 형식
|
||||
- **표준 보험코드**: 9자리 문자열 (예: `060600420`, `062401050`)
|
||||
- 일부 코드는 0으로 시작함
|
||||
|
||||
### 2. Excel 읽기 문제
|
||||
```python
|
||||
# 현재 상황
|
||||
Excel 파일의 제품코드 컬럼 → pandas가 int64로 자동 인식
|
||||
060600420 → 60600420 (앞의 0이 사라짐)
|
||||
062401050 → 62401050 (앞의 0이 사라짐)
|
||||
```
|
||||
|
||||
### 3. DB 매핑 실패
|
||||
- DB의 `herb_items.insurance_code`: `"060600420"` (9자리 문자열)
|
||||
- Excel에서 읽은 값: `60600420` (8자리 숫자)
|
||||
- **결과**: 매칭 실패 → 새로운 herb_item 생성
|
||||
|
||||
## 현재 코드 분석
|
||||
|
||||
### excel_processor.py (19번 줄)
|
||||
```python
|
||||
HANISARANG_MAPPING = {
|
||||
'품목명': 'herb_name',
|
||||
'제품코드': 'insurance_code', # 여기서 매핑은 되지만 타입 처리 안함
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### app.py (577-589번 줄)
|
||||
```python
|
||||
# 약재 확인/생성
|
||||
cursor.execute("""
|
||||
SELECT herb_item_id FROM herb_items
|
||||
WHERE insurance_code = ? OR herb_name = ?
|
||||
""", (row.get('insurance_code'), row['herb_name'])) # insurance_code가 숫자로 들어옴
|
||||
|
||||
if not herb:
|
||||
# 매칭 실패 시 새로 생성 (잘못된 코드로)
|
||||
cursor.execute("""
|
||||
INSERT INTO herb_items (insurance_code, herb_name)
|
||||
VALUES (?, ?)
|
||||
""", (row.get('insurance_code'), row['herb_name']))
|
||||
```
|
||||
|
||||
## 해결 방안
|
||||
|
||||
### 방안 1: Excel 읽을 때 문자열로 처리 (권장)
|
||||
```python
|
||||
# excel_processor.py 수정
|
||||
def read_excel(self, file_path):
|
||||
try:
|
||||
# 제품코드를 문자열로 읽도록 dtype 지정
|
||||
self.df_original = pd.read_excel(
|
||||
file_path,
|
||||
dtype={'제품코드': str, 'insurance_code': str}
|
||||
)
|
||||
# 또는 converters 사용
|
||||
# converters={'제품코드': lambda x: str(x).zfill(9)}
|
||||
```
|
||||
|
||||
### 방안 2: 처리 시 9자리로 패딩
|
||||
```python
|
||||
# excel_processor.py의 process_hanisarang/process_haninfo 메소드에서
|
||||
if 'insurance_code' in df_mapped.columns:
|
||||
# 숫자로 읽힌 경우 9자리로 패딩
|
||||
df_mapped['insurance_code'] = df_mapped['insurance_code'].apply(
|
||||
lambda x: str(int(x)).zfill(9) if pd.notna(x) and str(x).isdigit() else x
|
||||
)
|
||||
```
|
||||
|
||||
### 방안 3: app.py에서 매핑 시 보정
|
||||
```python
|
||||
# app.py의 upload_purchase_excel 함수에서
|
||||
insurance_code = row.get('insurance_code')
|
||||
if insurance_code and str(insurance_code).isdigit():
|
||||
# 숫자인 경우 9자리로 패딩
|
||||
insurance_code = str(int(insurance_code)).zfill(9)
|
||||
|
||||
cursor.execute("""
|
||||
SELECT herb_item_id FROM herb_items
|
||||
WHERE insurance_code = ? OR herb_name = ?
|
||||
""", (insurance_code, row['herb_name']))
|
||||
```
|
||||
|
||||
## 영향 범위
|
||||
|
||||
### 이미 잘못 등록된 데이터
|
||||
```sql
|
||||
-- 잘못된 보험코드로 등록된 herb_items 확인
|
||||
SELECT herb_item_id, herb_name, insurance_code
|
||||
FROM herb_items
|
||||
WHERE length(insurance_code) = 8
|
||||
AND insurance_code NOT LIKE 'A%';
|
||||
```
|
||||
|
||||
### 수정 필요 테이블
|
||||
1. `herb_items` - insurance_code 수정
|
||||
2. `purchase_receipt_lines` - 잘못된 herb_item_id 참조
|
||||
3. `inventory_lots` - 잘못된 herb_item_id 참조
|
||||
|
||||
## 권장 해결 순서
|
||||
|
||||
1. **즉시 조치**: `excel_processor.py` 수정하여 제품코드를 문자열로 읽도록 처리
|
||||
2. **데이터 정리**: 기존 잘못 등록된 herb_items 정리
|
||||
3. **검증 로직 추가**: 보험코드 형식 검증 (9자리 또는 특정 패턴)
|
||||
4. **테스트**: 샘플 파일로 입고 처리 테스트
|
||||
|
||||
## 추가 고려사항
|
||||
|
||||
1. **보험코드 형식 표준화**
|
||||
- 9자리 숫자: `060600420`
|
||||
- 영문+숫자: `A001100`
|
||||
- 기타 형식 확인 필요
|
||||
|
||||
2. **Excel 파일 형식 가이드**
|
||||
- 제품코드를 텍스트 형식으로 저장하도록 안내
|
||||
- 또는 '060600420 형태로 입력 (앞에 ' 추가)
|
||||
|
||||
3. **중복 방지**
|
||||
- 같은 약재가 다른 insurance_code로 중복 등록되는 것 방지
|
||||
- 약재명 + 제조사로 추가 검증
|
||||
180
docs/입고_프로세스_개선방안.md
Normal file
180
docs/입고_프로세스_개선방안.md
Normal file
@ -0,0 +1,180 @@
|
||||
# 입고 프로세스 개선 방안
|
||||
|
||||
## 현재 구조 이해
|
||||
|
||||
### 3단계 데이터 계층
|
||||
```
|
||||
1. herb_masters (454개)
|
||||
- 성분코드(ingredient_code) 기준 마스터
|
||||
- 예: 3400H1AHM = 인삼
|
||||
|
||||
2. herb_products (53,769개)
|
||||
- 성분코드별 보험코드 매핑 (참조 테이블)
|
||||
- 예: 060600420 = 신흥인삼 → 성분코드 3400H1AHM
|
||||
- 예: 060801010 = 세화인삼 → 성분코드 3400H1AHM
|
||||
|
||||
3. herb_items (40개)
|
||||
- 실제 사용/재고 관리 단위
|
||||
- ingredient_code + insurance_code 모두 보유
|
||||
```
|
||||
|
||||
## 현재 문제점
|
||||
|
||||
### 1. Excel 입고 시 보험코드 처리 문제
|
||||
- Excel에서 보험코드를 숫자로 읽음: `060600420` → `60600420`
|
||||
- DB 매핑 실패 → 새로운 herb_item 생성 (중복/잘못된 데이터)
|
||||
|
||||
### 2. 성분코드 연결 누락
|
||||
- 입고 시 보험코드만으로 herb_item 생성
|
||||
- ingredient_code 연결 안 됨
|
||||
- 성분코드 기준 재고 집계 불가
|
||||
|
||||
## 개선된 입고 프로세스
|
||||
|
||||
### 1단계: Excel 읽기 개선
|
||||
```python
|
||||
# excel_processor.py 수정
|
||||
def read_excel(self, file_path):
|
||||
# 제품코드를 문자열로 읽기
|
||||
self.df_original = pd.read_excel(
|
||||
file_path,
|
||||
dtype={'제품코드': str}
|
||||
)
|
||||
|
||||
def process_hanisarang/haninfo(self):
|
||||
# 보험코드 9자리 패딩 처리
|
||||
if 'insurance_code' in df_mapped.columns:
|
||||
df_mapped['insurance_code'] = df_mapped['insurance_code'].apply(
|
||||
lambda x: str(x).zfill(9) if pd.notna(x) and str(x).isdigit() else x
|
||||
)
|
||||
```
|
||||
|
||||
### 2단계: 보험코드 → 성분코드 매핑
|
||||
```python
|
||||
# app.py의 upload_purchase_excel 함수 수정
|
||||
|
||||
# 1. 보험코드로 herb_products에서 성분코드 찾기
|
||||
insurance_code = str(row.get('insurance_code')).zfill(9) # 9자리 패딩
|
||||
|
||||
cursor.execute("""
|
||||
SELECT DISTINCT ingredient_code, product_name, company_name
|
||||
FROM herb_products
|
||||
WHERE product_code = ?
|
||||
""", (insurance_code,))
|
||||
product_info = cursor.fetchone()
|
||||
|
||||
if product_info:
|
||||
ingredient_code = product_info[0]
|
||||
|
||||
# 2. herb_items에서 해당 보험코드 제품 확인
|
||||
cursor.execute("""
|
||||
SELECT herb_item_id
|
||||
FROM herb_items
|
||||
WHERE insurance_code = ?
|
||||
""", (insurance_code,))
|
||||
herb_item = cursor.fetchone()
|
||||
|
||||
if not herb_item:
|
||||
# 3. 새 제품 생성 (ingredient_code 포함!)
|
||||
cursor.execute("""
|
||||
INSERT INTO herb_items (
|
||||
ingredient_code,
|
||||
insurance_code,
|
||||
herb_name,
|
||||
specification
|
||||
) VALUES (?, ?, ?, ?)
|
||||
""", (
|
||||
ingredient_code,
|
||||
insurance_code,
|
||||
product_info[1], # product_name
|
||||
product_info[2] # company_name
|
||||
))
|
||||
herb_item_id = cursor.lastrowid
|
||||
else:
|
||||
herb_item_id = herb_item[0]
|
||||
else:
|
||||
# herb_products에 없는 경우 (비보험 약재 등)
|
||||
# 기존 로직 유지 또는 경고
|
||||
pass
|
||||
```
|
||||
|
||||
## 성분코드 기준 재고 관리
|
||||
|
||||
### 재고 조회 쿼리
|
||||
```sql
|
||||
-- 성분코드별 통합 재고 조회
|
||||
SELECT
|
||||
hm.ingredient_code,
|
||||
hm.herb_name as master_name,
|
||||
hm.herb_name_hanja,
|
||||
COUNT(DISTINCT hi.herb_item_id) as product_count,
|
||||
COUNT(DISTINCT hi.insurance_code) as insurance_code_count,
|
||||
COUNT(DISTINCT il.lot_id) as lot_count,
|
||||
COALESCE(SUM(il.quantity_onhand), 0) as total_stock,
|
||||
GROUP_CONCAT(DISTINCT hi.specification) as companies
|
||||
FROM herb_masters hm
|
||||
LEFT JOIN herb_items hi ON hm.ingredient_code = hi.ingredient_code
|
||||
LEFT JOIN inventory_lots il ON hi.herb_item_id = il.herb_item_id
|
||||
WHERE hm.is_active = 1
|
||||
GROUP BY hm.ingredient_code
|
||||
ORDER BY hm.herb_name;
|
||||
```
|
||||
|
||||
### 조제 시 제품 선택
|
||||
```sql
|
||||
-- 성분코드로 가용 제품 조회
|
||||
SELECT
|
||||
hi.herb_item_id,
|
||||
hi.insurance_code,
|
||||
hi.herb_name as product_name,
|
||||
hi.specification as company,
|
||||
SUM(il.quantity_onhand) as available_stock
|
||||
FROM herb_items hi
|
||||
JOIN inventory_lots il ON hi.herb_item_id = il.herb_item_id
|
||||
WHERE hi.ingredient_code = ?
|
||||
AND il.quantity_onhand > 0
|
||||
GROUP BY hi.herb_item_id
|
||||
ORDER BY available_stock DESC;
|
||||
```
|
||||
|
||||
## 구현 우선순위
|
||||
|
||||
### 1. 즉시 수정 (보험코드 문제 해결)
|
||||
- [ ] excel_processor.py: 제품코드 문자열 처리
|
||||
- [ ] app.py: 9자리 패딩 로직 추가
|
||||
|
||||
### 2. 데이터 정리
|
||||
- [ ] 기존 잘못된 herb_items 정리
|
||||
- [ ] ingredient_code 누락된 항목 업데이트
|
||||
|
||||
### 3. 프로세스 개선
|
||||
- [ ] 입고 시 herb_products 참조하여 성분코드 자동 연결
|
||||
- [ ] 성분코드 기준 재고 조회 API 추가
|
||||
|
||||
### 4. UI 개선
|
||||
- [ ] 재고 현황을 성분코드 기준으로 표시
|
||||
- [ ] 제품별 상세 보기 추가
|
||||
|
||||
## 기대 효과
|
||||
|
||||
1. **정확한 매핑**: 보험코드 → 성분코드 자동 연결
|
||||
2. **통합 재고 관리**: 성분코드 기준으로 여러 제품의 재고 통합 관리
|
||||
3. **유연한 조제**: 같은 성분의 다른 제품 선택 가능
|
||||
4. **데이터 일관성**: 표준 코드 체계 준수
|
||||
|
||||
## 추가 고려사항
|
||||
|
||||
### 비보험 약재 처리
|
||||
- herb_products에 없는 약재 입고 시
|
||||
- 수동으로 성분코드 매핑 또는
|
||||
- 별도 비보험 약재 테이블 관리
|
||||
|
||||
### 검증 로직
|
||||
- 보험코드 형식 검증 (9자리 숫자)
|
||||
- 중복 제품 생성 방지
|
||||
- 성분코드 매핑 실패 시 경고
|
||||
|
||||
### 마스터 데이터 관리
|
||||
- herb_products 정기 업데이트
|
||||
- 신규 보험코드 추가 프로세스
|
||||
- 성분코드 변경 이력 관리
|
||||
460
docs/프로젝트_전체_분석.md
Normal file
460
docs/프로젝트_전체_분석.md
Normal file
@ -0,0 +1,460 @@
|
||||
# kdrug 프로젝트 전체 분석 보고서
|
||||
|
||||
## 목차
|
||||
1. [프로젝트 개요](#프로젝트-개요)
|
||||
2. [시스템 아키텍처](#시스템-아키텍처)
|
||||
3. [디렉토리 구조](#디렉토리-구조)
|
||||
4. [데이터베이스 설계](#데이터베이스-설계)
|
||||
5. [백엔드 구조](#백엔드-구조)
|
||||
6. [프론트엔드 구조](#프론트엔드-구조)
|
||||
7. [주요 기능 분석](#주요-기능-분석)
|
||||
8. [비즈니스 로직](#비즈니스-로직)
|
||||
9. [기술 스택](#기술-스택)
|
||||
10. [개선 권장사항](#개선-권장사항)
|
||||
|
||||
---
|
||||
|
||||
## 프로젝트 개요
|
||||
|
||||
### 프로젝트명
|
||||
**kdrug - 한의원 약재 관리 시스템**
|
||||
|
||||
### 목적
|
||||
한의원 및 한약방을 위한 웹 기반 통합 관리 시스템으로, 약재 재고 관리, 처방 관리, 조제 관리, 환자 관리 등을 효율적으로 처리하는 것을 목표로 합니다.
|
||||
|
||||
### 주요 특징
|
||||
- 건강보험 표준 약재 코드 기반 체계적 관리
|
||||
- Excel 입고장 자동 처리 (한의사랑, 한의정보 형식)
|
||||
- FIFO(선입선출) 기반 로트별 재고 관리
|
||||
- 2단계 약재 체계 (마스터 약재 → 제품)
|
||||
- 정확한 원가 계산 및 추적
|
||||
- 모바일 친화적 환자 문진표 시스템
|
||||
|
||||
### 현재 상태 (2026-02-16 기준)
|
||||
- 데이터베이스: 16MB
|
||||
- 약재 마스터: 454개
|
||||
- 표준 제품: 53,769개
|
||||
- 실사용 제품: 40개
|
||||
- 등록 처방: 2개
|
||||
- 조제 내역: 3건
|
||||
- 제조사: 128개
|
||||
|
||||
---
|
||||
|
||||
## 시스템 아키텍처
|
||||
|
||||
### 전체 구조
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 웹 브라우저 (클라이언트) │
|
||||
│ - Single Page Application (SPA) │
|
||||
│ - Bootstrap 5.1.3 + jQuery 3.6.0 │
|
||||
│ - RESTful API 통신 │
|
||||
└──────────────────┬──────────────────────┘
|
||||
│ HTTP/AJAX
|
||||
│ Port 5001
|
||||
┌──────────────────▼──────────────────────┐
|
||||
│ Flask 웹 서버 (백엔드) │
|
||||
│ - app.py: REST API 엔드포인트 │
|
||||
│ - excel_processor.py: Excel 처리 │
|
||||
│ - 트랜잭션 관리, 비즈니스 로직 │
|
||||
└──────────────────┬──────────────────────┘
|
||||
│ SQL
|
||||
┌──────────────────▼──────────────────────┐
|
||||
│ SQLite 데이터베이스 │
|
||||
│ - database/kdrug.db (16MB) │
|
||||
│ - 26개 테이블 │
|
||||
│ - 정규화된 관계형 설계 │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 데이터 플로우
|
||||
```
|
||||
입고 → 로트 생성 → 재고 증가 → 조제 시 소비 → 재고 감소 → 원가 계산
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
Excel lot_id inventory_lots FIFO 차감 stock_ledger 원가추적
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 디렉토리 구조
|
||||
|
||||
### 주요 디렉토리
|
||||
```
|
||||
/root/kdrug/
|
||||
├── 📄 Core Files
|
||||
│ ├── app.py (1,916줄) # Flask 애플리케이션
|
||||
│ ├── excel_processor.py (285줄) # Excel 처리 모듈
|
||||
│ └── run_server.sh # 서버 실행 스크립트
|
||||
│
|
||||
├── 📁 templates/ # HTML 템플릿
|
||||
│ ├── index.html (1,233줄) # 메인 관리 화면
|
||||
│ └── survey.html (881줄) # 환자 문진표
|
||||
│
|
||||
├── 📁 static/ # 정적 파일
|
||||
│ └── app.js (2,386줄) # 프론트엔드 JavaScript
|
||||
│
|
||||
├── 📁 database/ # 데이터베이스
|
||||
│ ├── kdrug.db (16MB) # 메인 DB ⭐
|
||||
│ ├── schema.sql (229줄) # 스키마 정의
|
||||
│ └── [기타 SQL 파일들]
|
||||
│
|
||||
├── 📁 docs/ # 프로젝트 문서
|
||||
│ ├── api_documentation.md # API 명세
|
||||
│ ├── database_schema.md # DB 스키마
|
||||
│ ├── database_erd.md # ER 다이어그램
|
||||
│ └── [기타 문서들]
|
||||
│
|
||||
├── 📁 refactoring/ # 리팩토링 스크립트
|
||||
├── 📁 sample/ # 샘플 데이터
|
||||
├── 📁 uploads/ # 업로드 파일
|
||||
├── 📁 backups/ # 백업 파일
|
||||
└── 📁 .claude/ # Claude AI 설정
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 데이터베이스 설계
|
||||
|
||||
### 테이블 구조 (26개 테이블)
|
||||
|
||||
#### 1. 핵심 마스터 테이블
|
||||
| 테이블명 | 레코드수 | 설명 |
|
||||
|---------|---------|------|
|
||||
| herb_masters | 454 | 주성분코드 기반 약재 마스터 |
|
||||
| herb_items | 40 | 제조사별 실제 제품 |
|
||||
| herb_products | 53,769 | 건강보험 표준 제품 목록 |
|
||||
| product_companies | 128 | 제조/유통 업체 |
|
||||
| formulas | 2 | 처방 마스터 |
|
||||
| patients | - | 환자 정보 |
|
||||
|
||||
#### 2. 재고 관리 테이블
|
||||
| 테이블명 | 설명 |
|
||||
|---------|------|
|
||||
| inventory_lots | 로트별 재고 (FIFO 관리) |
|
||||
| stock_ledger | 모든 재고 변동 이력 |
|
||||
| stock_adjustments | 재고 조정 헤더 |
|
||||
| stock_adjustment_details | 재고 조정 상세 |
|
||||
|
||||
#### 3. 조제 관리 테이블
|
||||
| 테이블명 | 설명 |
|
||||
|---------|------|
|
||||
| compounds | 조제 내역 |
|
||||
| compound_ingredients | 조제별 약재 구성 |
|
||||
| compound_consumptions | 로트별 실제 소비 내역 |
|
||||
|
||||
#### 4. 처방 관리 테이블
|
||||
| 테이블명 | 설명 |
|
||||
|---------|------|
|
||||
| formula_ingredients | 처방 구성 (ingredient_code 기반) |
|
||||
|
||||
#### 5. 입고 관리 테이블
|
||||
| 테이블명 | 설명 |
|
||||
|---------|------|
|
||||
| suppliers | 도매상 정보 |
|
||||
| purchase_receipts | 입고장 헤더 |
|
||||
| purchase_receipt_lines | 입고장 상세 |
|
||||
|
||||
#### 6. 기타 테이블
|
||||
| 테이블명 | 설명 |
|
||||
|---------|------|
|
||||
| herb_efficacy_tags | 효능 태그 (18개) |
|
||||
| herb_item_tags | 약재-태그 연결 |
|
||||
| survey_templates | 문진표 템플릿 |
|
||||
| patient_surveys | 환자별 문진표 |
|
||||
| survey_responses | 문진표 응답 |
|
||||
| survey_progress | 문진표 진행 상태 |
|
||||
|
||||
### 주요 관계
|
||||
1. **약재 계층**: herb_masters → herb_items → inventory_lots
|
||||
2. **처방-조제**: formulas → formula_ingredients → compounds → compound_ingredients
|
||||
3. **재고 추적**: purchase_receipts → inventory_lots → compound_consumptions
|
||||
4. **원가 관리**: lot별 unit_price_per_g → FIFO 기반 원가 계산
|
||||
|
||||
---
|
||||
|
||||
## 백엔드 구조
|
||||
|
||||
### Flask 애플리케이션 (app.py)
|
||||
|
||||
#### API 엔드포인트 (7개 카테고리)
|
||||
|
||||
##### 1. 약재 관리 API
|
||||
- `GET /api/herbs` - 약재 제품 목록
|
||||
- `GET /api/herbs/masters` - 마스터 약재 목록
|
||||
- `GET /api/herbs/by-ingredient/{code}` - 성분코드별 제품
|
||||
- `GET /api/herbs/{id}/available-lots` - 가용 로트 조회
|
||||
|
||||
##### 2. 처방 관리 API
|
||||
- `GET /api/formulas` - 처방 목록
|
||||
- `POST /api/formulas` - 처방 등록
|
||||
- `GET /api/formulas/{id}/ingredients` - 처방 구성 조회
|
||||
|
||||
##### 3. 조제 관리 API
|
||||
- `POST /api/compounds` - 조제 실행
|
||||
- `GET /api/compounds/recent` - 최근 조제 내역
|
||||
- `GET /api/compounds/{id}` - 조제 상세
|
||||
|
||||
##### 4. 재고 관리 API
|
||||
- `GET /api/inventory/summary` - 재고 현황 요약
|
||||
- `GET /api/inventory/low-stock` - 재고 부족 약재
|
||||
- `GET /api/stock-ledger` - 재고 원장
|
||||
|
||||
##### 5. 환자 관리 API
|
||||
- `GET /api/patients` - 환자 목록
|
||||
- `POST /api/patients` - 환자 등록
|
||||
- `GET /api/patients/{id}/prescriptions` - 환자 처방 이력
|
||||
|
||||
##### 6. 구매/입고 API
|
||||
- `POST /api/purchases/upload` - Excel 업로드
|
||||
- `POST /api/purchases/receipts` - 입고장 등록
|
||||
- `GET /api/purchases/receipts` - 입고장 조회
|
||||
|
||||
##### 7. 재고 조정 API
|
||||
- `POST /api/stock-adjustments` - 재고 보정
|
||||
- `GET /api/stock-adjustments` - 보정 내역 조회
|
||||
|
||||
### Excel 처리 모듈 (excel_processor.py)
|
||||
|
||||
#### 주요 기능
|
||||
1. **형식 자동 감지**: 한의사랑, 한의정보 형식 자동 인식
|
||||
2. **컬럼 매핑**: 다양한 컬럼명 유연한 처리
|
||||
3. **데이터 변환**: 숫자, 날짜, 텍스트 자동 변환
|
||||
4. **검증 및 요약**: 데이터 검증 및 처리 결과 리포트
|
||||
|
||||
---
|
||||
|
||||
## 프론트엔드 구조
|
||||
|
||||
### 메인 관리 화면 (index.html)
|
||||
|
||||
#### 7개 주요 섹션
|
||||
1. **대시보드**: 통계 요약, 최근 조제 내역
|
||||
2. **환자 관리**: 환자 등록, 조회, 처방 내역
|
||||
3. **입고 관리**: Excel 업로드, 입고장 관리
|
||||
4. **처방 관리**: 처방 등록, 구성 관리
|
||||
5. **조제 관리**: 조제 실행, 내역 조회
|
||||
6. **재고 현황**: 재고 조회, 보정, 원장
|
||||
7. **약재 관리**: 마스터 약재 관리
|
||||
|
||||
### JavaScript 애플리케이션 (app.js)
|
||||
|
||||
#### 주요 기능 모듈
|
||||
1. **페이지 네비게이션**: SPA 방식 클라이언트 라우팅
|
||||
2. **API 통신**: jQuery 기반 RESTful API 호출
|
||||
3. **동적 UI 생성**: 테이블, 폼, 모달 동적 생성
|
||||
4. **데이터 로딩**: 20+ 데이터 로딩 함수
|
||||
5. **이벤트 처리**: 30+ 이벤트 핸들러
|
||||
6. **유틸리티**: 포맷팅, 계산, 검증
|
||||
|
||||
### 환자 문진표 (survey.html)
|
||||
|
||||
#### 모바일 최적화 설계
|
||||
- **반응형 레이아웃**: 모바일 친화적 UI
|
||||
- **진행률 추적**: 실시간 진행 상태 표시
|
||||
- **카테고리 네비게이션**: 9개 건강 카테고리
|
||||
- **자동 저장**: 로컬스토리지 + 서버 동기화
|
||||
- **오프라인 지원**: 로컬 백업 및 복원
|
||||
|
||||
---
|
||||
|
||||
## 주요 기능 분석
|
||||
|
||||
### 1. 재고 관리 시스템
|
||||
|
||||
#### 2단계 약재 체계
|
||||
```
|
||||
1단계: herb_masters (성분코드 기준)
|
||||
↓
|
||||
2단계: herb_items (제조사별 제품)
|
||||
↓
|
||||
로트: inventory_lots (입고 단위)
|
||||
```
|
||||
|
||||
#### FIFO 재고 관리
|
||||
- 선입선출 원칙으로 자동 차감
|
||||
- 로트별 추적 가능
|
||||
- 정확한 원가 계산
|
||||
|
||||
### 2. Excel 입고 자동화
|
||||
|
||||
#### 지원 형식
|
||||
- 한의사랑 거래명세표
|
||||
- 한의정보 거래명세표
|
||||
- 자동 형식 감지 및 처리
|
||||
|
||||
#### 처리 프로세스
|
||||
```
|
||||
Excel 업로드 → 형식 감지 → 데이터 추출 → 검증 → DB 저장 → 로트 생성
|
||||
```
|
||||
|
||||
### 3. 처방-조제 시스템
|
||||
|
||||
#### 처방 구성
|
||||
- ingredient_code 기반 (유연한 제품 선택)
|
||||
- 기본 첩수/파우치 설정
|
||||
- 1첩당 용량 관리
|
||||
|
||||
#### 조제 프로세스
|
||||
```
|
||||
처방 선택 → 제품 선택 → 원산지/로트 선택 → 조제 실행 → 재고 차감
|
||||
```
|
||||
|
||||
### 4. 원가 관리
|
||||
|
||||
#### 원가 계산 방식
|
||||
- 로트별 단가 기준
|
||||
- FIFO 차감 시 실제 원가 추적
|
||||
- 조제별 정확한 원가 집계
|
||||
|
||||
### 5. 환자 문진표 시스템
|
||||
|
||||
#### 특징
|
||||
- 모바일 최적화
|
||||
- 9개 건강 카테고리
|
||||
- 진행률 추적
|
||||
- 자동 저장/복원
|
||||
|
||||
---
|
||||
|
||||
## 비즈니스 로직
|
||||
|
||||
### 1. 단위 환산 체계
|
||||
```
|
||||
1제 = 20첩 (기본값, 조정 가능)
|
||||
1제 = 30파우치 (기본값, 조정 가능)
|
||||
```
|
||||
|
||||
### 2. 재고 차감 로직
|
||||
```python
|
||||
def consume_inventory(herb_item_id, quantity_needed):
|
||||
# 1. 가용 로트 조회 (FIFO 순서)
|
||||
lots = get_available_lots(herb_item_id, order='received_date')
|
||||
|
||||
# 2. 순차적 차감
|
||||
consumptions = []
|
||||
for lot in lots:
|
||||
if quantity_needed <= 0:
|
||||
break
|
||||
consumed = min(lot.quantity_onhand, quantity_needed)
|
||||
lot.quantity_onhand -= consumed
|
||||
quantity_needed -= consumed
|
||||
consumptions.append({
|
||||
'lot_id': lot.id,
|
||||
'quantity': consumed,
|
||||
'unit_price': lot.unit_price_per_g
|
||||
})
|
||||
|
||||
# 3. stock_ledger 기록
|
||||
# 4. compound_consumptions 기록
|
||||
return consumptions
|
||||
```
|
||||
|
||||
### 3. 원가 계산
|
||||
```python
|
||||
def calculate_cost(consumptions):
|
||||
total_cost = 0
|
||||
for consumption in consumptions:
|
||||
cost = consumption['quantity'] * consumption['unit_price']
|
||||
total_cost += cost
|
||||
return total_cost
|
||||
```
|
||||
|
||||
### 4. 재고 보정 유형
|
||||
- **감모**: 자연 감소, 손실
|
||||
- **발견**: 추가 발견된 재고
|
||||
- **재고조사**: 실사 보정
|
||||
- **반품**: 반품 처리
|
||||
- **기타**: 기타 사유
|
||||
|
||||
---
|
||||
|
||||
## 기술 스택
|
||||
|
||||
### 백엔드
|
||||
- **언어**: Python 3.12
|
||||
- **프레임워크**: Flask
|
||||
- **데이터베이스**: SQLite 3
|
||||
- **Excel 처리**: pandas, openpyxl
|
||||
- **CORS**: flask-cors
|
||||
|
||||
### 프론트엔드
|
||||
- **HTML5/CSS3**: 시맨틱 마크업
|
||||
- **JavaScript**: ES6+
|
||||
- **라이브러리**:
|
||||
- jQuery 3.6.0 (DOM, AJAX)
|
||||
- Bootstrap 5.1.3 (UI Framework)
|
||||
- Bootstrap Icons 1.8.1
|
||||
|
||||
### 개발/운영 환경
|
||||
- **OS**: Linux (6.8.4-3-pve)
|
||||
- **가상환경**: Python venv
|
||||
- **포트**: 5001
|
||||
- **프로세스 관리**: bash script
|
||||
|
||||
---
|
||||
|
||||
## 개선 권장사항
|
||||
|
||||
### 1. 성능 최적화
|
||||
- [ ] 데이터베이스 인덱스 최적화
|
||||
- [ ] API 페이지네이션 구현
|
||||
- [ ] 캐싱 전략 도입
|
||||
- [ ] 대용량 데이터 처리 개선
|
||||
|
||||
### 2. 보안 강화
|
||||
- [ ] 사용자 인증/인가 시스템
|
||||
- [ ] API 접근 제어
|
||||
- [ ] SQL Injection 방어 강화
|
||||
- [ ] XSS 방어 강화
|
||||
|
||||
### 3. 코드 품질
|
||||
- [ ] 코드 모듈화 (app.py 분리)
|
||||
- [ ] 에러 핸들링 개선
|
||||
- [ ] 단위 테스트 추가
|
||||
- [ ] API 문서 자동화 (Swagger)
|
||||
|
||||
### 4. 사용자 경험
|
||||
- [ ] 실시간 알림 시스템
|
||||
- [ ] 대시보드 커스터마이징
|
||||
- [ ] 고급 검색 기능
|
||||
- [ ] 다크 모드 지원
|
||||
|
||||
### 5. 기능 확장
|
||||
- [ ] 바코드/QR 코드 지원
|
||||
- [ ] 보고서 생성 기능
|
||||
- [ ] 다중 사업장 지원
|
||||
- [ ] 모바일 앱 개발
|
||||
|
||||
### 6. 데이터 관리
|
||||
- [ ] 자동 백업 시스템
|
||||
- [ ] 데이터 마이그레이션 도구
|
||||
- [ ] 감사 로그 시스템
|
||||
- [ ] 데이터 분석 대시보드
|
||||
|
||||
---
|
||||
|
||||
## 결론
|
||||
|
||||
kdrug 프로젝트는 한의원의 실무 요구사항을 충실히 반영한 **실용적이고 체계적인 관리 시스템**입니다.
|
||||
|
||||
### 강점
|
||||
1. **표준화**: 건강보험 표준 코드 기반
|
||||
2. **자동화**: Excel 입고 자동 처리
|
||||
3. **정확성**: FIFO 기반 정확한 원가 추적
|
||||
4. **사용성**: 직관적인 UI/UX
|
||||
5. **확장성**: 모듈화된 구조
|
||||
|
||||
### 핵심 가치
|
||||
- 업무 효율성 향상
|
||||
- 정확한 재고 관리
|
||||
- 체계적인 원가 관리
|
||||
- 환자 서비스 품질 향상
|
||||
|
||||
프로젝트는 지속적인 개선과 확장을 통해 한의원 통합 관리 솔루션으로 발전할 수 있는 견고한 기반을 갖추고 있습니다.
|
||||
|
||||
---
|
||||
|
||||
**작성일**: 2026-02-16
|
||||
**작성자**: Claude AI Assistant
|
||||
**버전**: 1.0
|
||||
Loading…
Reference in New Issue
Block a user