# InsuRo 소식지/보험료 파일 분석을 서버 사이드로 전환

## 작업 레벨: Lv.2

## 프로젝트 시스템 3문서
- DevSystem: `/home/jay/workspace/memory/plans/anu-guide-system/plan.md`

## 프로젝트
- InsuRo: `/home/jay/projects/InsuRo`
- 서버: `/home/jay/projects/InsuRo/server` (FastAPI, port 8001)
- 배포: Cloudflare Pages + 서버는 Tailscale

## 배경
현재 소식지/보험료 PDF/PPTX 분석이 Supabase Edge Function (`parse-premium-file`)에서 Gemini API를 호출하는 구조인데, `GOOGLE_AI_API_KEY`가 미설정이라 "AI 분석 실패" 에러 발생.

**제이회장님 지시**: 외부 API(Gemini/Claude API) 대신, InsuRo 서버(아누 시스템)에서 직접 처리할 것.

## 현재 구조 (Edge Function)
```
프론트(AdminNewsletters.tsx, AdminPremiumData.tsx)
  → supabase.functions.invoke("parse-premium-file")
    → Supabase Edge Function
      → Gemini API (GOOGLE_AI_API_KEY 필요) ← 여기서 실패
      → Supabase DB update (parsed_text, company_name, title)
```

## 변경 후 구조 (서버 사이드)
```
프론트(AdminNewsletters.tsx, AdminPremiumData.tsx)
  → InsuRo 서버 API (/api/insuro/parse-premium-file)
    → pdfplumber로 PDF 텍스트 추출 (기존 ai_parser.py 활용)
    → python-pptx로 PPTX 텍스트 추출
    → 추출된 텍스트에서 보험사명/제목 자동 감지 (정규식 또는 간단한 룰 기반)
    → Supabase DB update (service_role key로)
```

## 구현 상세

### 1. 서버 엔드포인트 추가 (`main.py`)
```python
@app.post("/api/insuro/parse-premium-file")
async def parse_premium_file(request: Request):
    # body: { file_url, record_id, file_type, original_filename }
    # 1. Supabase Storage에서 파일 다운로드 (file_url)
    # 2. PDF → pdfplumber, PPTX → python-pptx 텍스트 추출
    # 3. 텍스트에서 보험사명 자동 감지 (한화, DB, 삼성, 교보 등 키워드 매칭)
    # 4. 제목 자동 생성 (파일명 또는 첫 줄)
    # 5. Supabase DB update: parsed_text, company_name, title, status
```

### 2. PDF/PPTX 텍스트 추출
- PDF: `ai_parser.py`의 기존 `extract_text_from_pdf()` 함수 재사용
- PPTX: `python-pptx` 라이브러리로 슬라이드별 텍스트 추출
  ```python
  from pptx import Presentation
  prs = Presentation(io.BytesIO(file_bytes))
  text = "\n".join(shape.text for slide in prs.slides for shape in slide.shapes if shape.has_text_frame)
  ```
- 의존성 추가 필요: `pip install python-pptx` (pdfplumber는 이미 설치됨)

### 3. 보험사 자동 감지
```python
COMPANY_PATTERNS = {
    "한화": ["한화", "hanwha"],
    "DB": ["DB손보", "DB생명", "DB손해"],
    "삼성": ["삼성생명", "삼성화재"],
    "교보": ["교보생명", "교보"],
    "현대": ["현대해상"],
    "메리츠": ["메리츠"],
    "NH": ["NH농협"],
    "KB": ["KB손보", "KB생명"],
    "신한": ["신한라이프"],
    "인카다이렉트": ["인카다이렉트", "inca"],
}
```

### 4. 프론트엔드 수정
`AdminNewsletters.tsx`와 `AdminPremiumData.tsx`에서:
```tsx
// Before: Supabase Edge Function
const { data, error } = await supabase.functions.invoke("parse-premium-file", { body: {...} });

// After: InsuRo 서버 API
const resp = await fetch(`${API_BASE}/api/insuro/parse-premium-file`, {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${session.access_token}` },
  body: JSON.stringify({ file_url, record_id, file_type, original_filename }),
});
const data = await resp.json();
```

- `API_BASE`는 `import.meta.env.VITE_INSURO_API_URL`을 사용 (메디스캔과 동일 패턴)

### 5. Supabase DB 업데이트 (서버에서)
서버가 service_role key로 Supabase에 직접 업데이트:
```python
# parsed_text, company_name, title, status 업데이트
supabase.table("premium_data").update({
    "parsed_text": extracted_text,
    "company_name": detected_company,
    "title": auto_title,
    "status": "completed"
}).eq("id", record_id).execute()
```

## affected_files
- `server/main.py` (수정 — 엔드포인트 추가)
- `server/requirements.txt` (수정 — python-pptx 추가)
- `src/pages/AdminNewsletters.tsx` (수정 — Edge Function → 서버 API 호출)
- `src/pages/AdminPremiumData.tsx` (수정 — Edge Function → 서버 API 호출)

## 검증 시나리오
1. 소식지 관리 → PDF 업로드 → "AI 분석 완료" 토스트 (에러 없음)
2. 보험료 데이터 → PPTX 업로드 → 텍스트 추출 + 보험사명 자동 감지 → 정상 표시
3. 추출된 텍스트가 DB에 저장되고 "텍스트 없음" 뱃지가 사라짐
4. npm run build 성공
5. 서버 재시작 후 엔드포인트 정상 응답 확인
