# MediScan Phase 1-A: PDF 파서 모듈 개발

## 작업 레벨: Lv.4 (대규모 신규 프로젝트 핵심 모듈)

## 프로젝트 3문서 참조
- 계획서: `/home/jay/workspace/memory/plans/mediscan/plan.md`
- 맥락노트: `/home/jay/workspace/memory/plans/mediscan/context-notes.md`
- 체크리스트: `/home/jay/workspace/memory/plans/mediscan/checklist.md`

## 배경
MediScan: 심평원/건보공단 PDF를 파싱하여 보험 고지의무를 자동 분석하는 웹 서비스.
Phase 1-A는 **PDF 파서 모듈**만 개발. 분석 엔진(Phase 1-B)과 분리하여 진행.

## 목표
심평원/건보공단 PDF 5종을 정확하게 파싱하여 구조화된 데이터(JSON)로 변환하는 Python 모듈 개발.

## PDF 샘플 위치
`/home/jay/projects/MediScan/docs/samples/`
- 세부진료정보.pdf (6p)
- 처방조제정보.pdf (5p)
- 자동차사고기본진료정보.pdf (1p)
- 자동차사고세부진료정보.pdf (5p)
- 건강검진결과.pdf (1p)

## PDF 테이블 구조 (사전 분석 완료)

### 1. 세부진료정보 (6p)
컬럼: 순번, 진료시작일, 병·의원&약국, 진료내역, 코드명, 1회투약량, 1일투여횟수, 총투약일수
- 수술/처치 판별의 핵심 소스
- 진료내역에 "진찰료/외래", "이학요법료" 등 카테고리 포함

### 2. 처방조제정보 (5p)
컬럼: 순번, 진료시작일, 병·의원&약국, 처방/조제, 약품명, 성분명, 1회투약량, 1일투여횟수, 총투약일수
- 누적 투약일수 산출의 핵심 소스
- 처방/조제 구분(외래/처방조제)

### 3. 자동차사고 기본진료정보 (1p)
컬럼: 순번, 진료시작일, 병·의원&약국, 진단과, 입원/외래, 진료일수, 주상병코드, 주상병명, 청구진료비총금액, 자동차보험총진료비
- ★ 일반 기본진료내역의 구조도 이와 유사할 것으로 추정
- 상병코드(KCD) + 상병명 추출 가능

### 4. 자동차사고 세부진료정보 (5p)
- 세부진료정보와 동일 구조 (자동차보험 항목)

### 5. 건강검진결과 (1p)
구조: 항목, 구분, 단위, 연도별 수치(10년분 가로 배치)
- 일반 테이블이 아닌 검진 항목별 시계열 데이터
- 항목: 신장, 체중, BMI, 혈압, 혈당, 콜레스테롤, 간기능 등

## 구현 사항

### 프로젝트 구조
```
/home/jay/projects/MediScan/
├── src/
│   ├── __init__.py
│   ├── parsers/
│   │   ├── __init__.py
│   │   ├── base.py           # 공통 파서 베이스 클래스
│   │   ├── detail_treatment.py   # 세부진료정보 파서
│   │   ├── prescription.py       # 처방조제정보 파서
│   │   ├── accident_basic.py     # 자동차사고 기본진료 파서
│   │   ├── accident_detail.py    # 자동차사고 세부진료 파서
│   │   ├── health_checkup.py     # 건강검진결과 파서
│   │   └── basic_treatment.py    # 기본진료내역 파서 (구조 추정 기반)
│   └── models/
│       ├── __init__.py
│       └── schemas.py        # Pydantic 모델 정의
├── tests/
│   ├── __init__.py
│   ├── test_detail_treatment.py
│   ├── test_prescription.py
│   ├── test_accident_basic.py
│   ├── test_accident_detail.py
│   └── test_health_checkup.py
├── requirements.txt
└── pyproject.toml
```

### 기술 스택
- Python 3.11+
- pdfplumber (테이블 추출 주력)
- PyMuPDF/fitz (텍스트 추출 보조)
- Pydantic v2 (데이터 모델)
- pytest (테스트)

### 파서 출력 형식 (각 PDF 타입별)

#### 세부진료정보 → JSON
```json
{
  "type": "detail_treatment",
  "source": "심평원",
  "records": [
    {
      "seq": 1,
      "treatment_date": "2025-08-23",
      "institution": "365열린메디칼의원",
      "category": "진찰료/외래",
      "code_name": "초진진찰료-의원",
      "dosage_per_time": 1,
      "times_per_day": 1,
      "total_days": 1
    }
  ]
}
```

#### 처방조제정보 → JSON
```json
{
  "type": "prescription",
  "source": "심평원",
  "records": [
    {
      "seq": 1,
      "treatment_date": "2024-10-08",
      "institution": "수원성모이비인후과의원",
      "rx_type": "외래",
      "drug_name": "에르덱스캡슐(에르도스테인)",
      "ingredient": "erdosteine",
      "dosage_per_time": 1,
      "times_per_day": 3,
      "total_days": 3
    }
  ]
}
```

#### 자동차사고 기본진료 → JSON
```json
{
  "type": "accident_basic_treatment",
  "source": "심평원",
  "records": [
    {
      "seq": 1,
      "treatment_date": "2024-12-18",
      "institution": "수원본바른한방병원",
      "department": "한방재활의학과",
      "visit_type": "외래",
      "treatment_days": 1,
      "disease_code": "BS134",
      "disease_name": "(한방)경추의염좌및긴장",
      "total_cost": 207300,
      "auto_insurance_cost": 0
    }
  ]
}
```

#### 건강검진결과 → JSON
```json
{
  "type": "health_checkup",
  "source": "건보공단",
  "checkup_years": ["2017", "2018", ...],
  "items": [
    {
      "item_name": "혈압(수축기/확장기)",
      "unit": "mmHg",
      "values": {"2026": "145/90", ...}
    }
  ]
}
```

### 핵심 처리 로직
1. **PDF 파일 타입 자동 감지**: 첫 페이지 텍스트에서 "세부진료정보", "처방조제정보", "기본진료내역" 등 키워드로 판별
2. **테이블 추출**: pdfplumber로 테이블 경계 감지 → 행/열 파싱
3. **다중 페이지 연결**: 테이블이 페이지를 넘어가는 경우 자동 연결
4. **텍스트 정규화**: 줄바꿈 제거, 공백 정리, 한글/영문 혼합 처리
5. **날짜 파싱**: "2025-08-23" 형식 통일
6. **숫자 파싱**: 금액(콤마), 일수, 투약량 등
7. **암호화 PDF 처리**: 비밀번호 입력 → qpdf/fitz 복호화 후 파싱

## 검증 시나리오

### 시나리오 1: 세부진료정보 파싱
- 입력: `/home/jay/projects/MediScan/docs/samples/세부진료정보.pdf`
- 성공 기준: 6페이지 전체 레코드 추출, 누락 0건, 컬럼 매핑 정확

### 시나리오 2: 처방조제정보 파싱
- 입력: 처방조제정보.pdf
- 성공 기준: 약품명+성분명+투약일수 정확 추출

### 시나리오 3: 자동차사고 기본진료 파싱
- 입력: 자동차사고기본진료정보.pdf
- 성공 기준: 상병코드+상병명 정확 추출, 비용 숫자 파싱

### 시나리오 4: 건강검진결과 파싱
- 입력: 건강검진결과.pdf
- 성공 기준: 10년분 검진 항목 시계열 데이터 추출

### 시나리오 5: 파일 타입 자동 감지
- 5개 PDF를 순서 무관하게 넣으면 각각 올바른 파서로 라우팅

## 주의사항
- ★★★ **PDF 파일에 실제 개인 의료정보가 포함되어 있음** → git에 커밋하지 말 것! .gitignore에 docs/samples/ 추가
- 테스트 시 파서 결과의 개인정보(이름, 주민번호 등)가 로그에 남지 않도록 주의
- pdfplumber가 테이블 감지 실패하면 PyMuPDF로 fallback
- 심평원 PDF는 웹 브라우저 인쇄→PDF 변환이라 일반 PDF와 구조 다를 수 있음

## 참고
- 프로젝트 디렉토리: `/home/jay/projects/MediScan/`
- MHS V9.7 릴리즈 노트: `/home/jay/projects/MediScan/docs/MHS V9.7 Update Log 2026-03-20.txt`
- MHS 사용자 가이드: `/home/jay/projects/MediScan/docs/MHS 사용자 가이드.pdf`