# 🤖 AI 자동발주시스템 통합 기획서

> 버전: 1.0
> 작성일: 2026-03-06
> 작성자: 용림 (with 약사님)
> 상태: 기획 완료, 개발 대기

## 📋 목차

1. 비전 및 목표
2. 현재 구현 현황
3. 시스템 아키텍처
4. AI 학습 요소
5. 핵심 기능 설계
6. 데이터 모델
7. API 설계
8. 자동화 레벨
9. 알림 시스템
10. 개발 로드맵
11. 성공 지표

## 1. 비전 및 목표

### 🎯 비전

> "약사님이 주문에 신경 쓰지 않아도 되는 약국"

AI가 사용량, 재고, 도매상 상황, 과거 주문 패턴을 학습하여:
- 언제 주문할지
- 어느 도매상에 주문할지
- 어떤 규격으로 주문할지
- 얼마나 주문할지

모든 것을 자동으로 결정하고 실행합니다.

### 핵심 가치

AS-IS | TO-BE
--- | ---
매일 재고 확인 | AI가 자동 모니터링
수동으로 도매상 선택 | AI가 최적 도매상 선택
경험에 의존한 주문량 | 데이터 기반 최적 주문량
주문 누락/지연 발생 | 선제적 자동 주문
배송 마감 놓침 | 마감시간 자동 알림

### 핵심 원칙

> "AI는 대체하는 것이 아니라, 약사님의 방식을 자동화합니다."

- 약사님이 항상 지오영에 먼저 주문하면 → AI도 지오영 우선
- 약사님이 300T보다 30T를 선호하면 → AI도 소량 주문
- 약사님이 여유 있게 주문하면 → AI도 안전 재고 확보
- 약사님이 가격에 민감하면 → AI도 최저가 추적 (OTC/비급여)

## 2. 현재 구현 현황

### 2.1 도매상 API (✅ 완료)

도매상 | 재고조회 | 장바구니 | 주문 | 취소/복원 | 잔고 | 월매출
--- | --- | --- | --- | --- | --- | ---
지오영 | ✅ | ✅ | ✅ 확정포함 | ✅ | ✅ | ✅
수인약품 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅
백제약품 | ✅ | ✅ | ✅ | ⏳ | ✅ | ✅

### 2.2 주문 DB (✅ 완료)

    orders.db
    ├── wholesalers        # 도매상 마스터
    ├── orders             # 주문 헤더
    ├── order_items        # 주문 품목
    ├── order_logs         # 주문 이력
    ├── order_context      # AI 학습용 컨텍스트 ⭐
    ├── daily_usage        # 일별 사용량 시계열
    └── order_patterns     # AI 분석 결과

### 2.3 배송 스케줄 (✅ 확인 완료)

    ┌──────────┬──────────┬──────────────┬──────────────┬──────────┐
    │ 도매상   │ 배송     │ 주문 마감    │ 도착 예정    │ 비고     │
    ├──────────┼──────────┼──────────────┼──────────────┼──────────┤
    │ 지오영   │ 오전     │ 10:00        │ 11:30        │ 당일     │
    │          │ 오후     │ 13:00        │ 15:00        │ 당일     │
    ├──────────┼──────────┼──────────────┼──────────────┼──────────┤
    │ 수인     │ 오후     │ 13:00        │ 14:30        │ 당일     │
    ├──────────┼──────────┼──────────────┼──────────────┼──────────┤
    │ 백제     │ 익일     │ 16:00        │ 다음날 15:00 │ ⚠️ 익일  │
    └──────────┴──────────┴──────────────┴──────────────┴──────────┘

### 2.4 UI (✅ 완료)

- Rx 사용량 페이지 (처방 기반)
- 장바구니 모달
- 도매상 잔고/월매출 모달

## 3. 시스템 아키텍처

### 전체 흐름

    ┌─────────────────────────────────────────────────────────────────┐
    │                     AI 자동발주시스템                            │
    └─────────────────────────────────────────────────────────────────┘
                                    │
            ┌───────────────────────┼───────────────────────┐
            ▼                       ▼                       ▼
    ┌───────────────┐      ┌───────────────┐      ┌───────────────┐
    │  데이터 수집   │      │   AI 분석     │      │   자동 실행    │
    │               │      │               │      │               │
    │ • POS 판매    │─────▶│ • 사용량 예측  │─────▶│ • 도매상 API  │
    │ • 처방전 조제  │      │ • 재고 분석   │      │ • 주문 실행   │
    │ • 현재 재고   │      │ • 주문 추천   │      │ • 결과 피드백  │
    │ • 도매상 재고  │      │ • 패턴 학습   │      │               │
    └───────────────┘      └───────────────┘      └───────────────┘
            │                       │                       │
            └───────────────────────┼───────────────────────┘
                                    ▼
                        ┌───────────────────┐
                        │    학습 루프       │
                        │                   │
                        │  주문 결과 평가    │
                        │  → 모델 업데이트   │
                        │  → 전략 조정      │
                        └───────────────────┘

### 컴포넌트 구조

    ┌──────────────────────────────────────────────────────────────────┐
    │                         데이터 레이어                             │
    ├──────────────────────────────────────────────────────────────────┤
    │  ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌────────────┐ │
    │  │  PIT3000   │  │   SQLite   │  │  지오영    │  │   수인     │ │
    │  │  (MSSQL)   │  │  Orders DB │  │   API      │  │   API      │ │
    │  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘  └─────┬──────┘ │
    │        └───────────────┴───────────────┴───────────────┘        │
    └────────────────────────────────┬─────────────────────────────────┘
                                     ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │                         서비스 레이어                             │
    ├──────────────────────────────────────────────────────────────────┤
    │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐  │
    │  │  InventorySync  │  │  UsageAnalyzer  │  │  OrderExecutor  │  │
    │  │  재고 동기화     │  │  사용량 분석    │  │  주문 실행      │  │
    │  └─────────────────┘  └─────────────────┘  └─────────────────┘  │
    │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐  │
    │  │  AIPredictor    │  │  AIOptimizer    │  │  AILearner      │  │
    │  │  수요 예측      │  │  규격/도매상    │  │  패턴 학습      │  │
    │  └─────────────────┘  └─────────────────┘  └─────────────────┘  │
    └──────────────────────────────────────────────────────────────────┘
                                     │
                                     ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │                         인터페이스 레이어                          │
    ├──────────────────────────────────────────────────────────────────┤
    │  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐  │
    │  │   웹 대시보드    │  │  알림 시스템    │  │   관리자 앱     │  │
    │  │  재고/주문/AI   │  │  카톡/텔레그램  │  │  수동 개입      │  │
    │  └─────────────────┘  └─────────────────┘  └─────────────────┘  │
    └──────────────────────────────────────────────────────────────────┘

## 4. AI 학습 요소

### 4.1 규격 선택 학습 (Spec Selection)

    ⚠️ 중요: 전문의약품(ETC)은 보험약가 고정!
    - 30T든 300T든 1T당 가격 동일
    - 단가 효율은 OTC/비급여에서만 의미 있음

    학습 데이터:
    - 약품별 과거 주문 규격 (30T, 100T, 300T, 500T)
    - 각 규격 선택 시점의 재고/사용량
    - 선택 결과 (남은 재고, 다음 주문까지 기간)
    - 도매상별 규격 재고 현황

    학습 목표:
    - 사용량 대비 최적 규격 예측
    - 재고 있는 규격 우선 선택
    - 낭비 최소화 (유통기한 고려)
    - 소분 vs 대용량 선호도 파악

예시 시나리오:
| 필요량 | 가능 규격 | AI 선택 | 이유 |
|--------|-----------|---------|------|
| 280T | 30T(재고50), 100T(품절), 300T(재고10) | 30T x 10 | 100T 품절, 소분 선호 |
| 800T | 30T(재고100), 300T(재고5) | 300T x 3 | 대량, 재고 충분 |
| 50T | 30T(재고20), 100T(재고10) | 30T x 2 | 소량, 빠른 회전 |

### 4.2 재고 전략 학습 (Inventory Strategy)

    학습 데이터:
    - 주문 시점의 재고 수준
    - 재고 소진까지 남은 일수
    - 주문 후 입고까지 리드타임
    - 품절 발생 이력

    학습 목표:
    - 약사님의 재고 선호도 파악
      - 타이트형: 최소 재고 유지 (현금 흐름 중시)
      - 여유형: 안전 재고 확보 (품절 방지 중시)

재고 전략 프로파일:

    class InventoryStrategy:
        TIGHT = {
            'safety_days': 2,      # 안전 재고 2일치
            'reorder_point': 0.8,  # 80% 소진 시 주문
            'order_coverage': 7    # 7일치 주문
        }

        MODERATE = {
            'safety_days': 5,
            'reorder_point': 0.6,
            'order_coverage': 14
        }

        CONSERVATIVE = {
            'safety_days': 10,
            'reorder_point': 0.5,
            'order_coverage': 30
        }

### 4.3 도매상 선택 학습 (Wholesaler Selection)

    학습 데이터:
    - 도매상별 주문 빈도
    - 도매상별 재고 상황
    - 도매상별 배송 스케줄
    - 월별 한도 사용량
    - 분할 주문 패턴

    학습 목표:
    - 기본 도매상 선호도
    - 상황별 대체 도매상
    - 한도 고려한 분배
    - 배송 시간 고려 (긴급 시)

도매상 선택 로직:

    def select_wholesaler(drug_code, quantity, need_by_time=None):
        """
        AI가 학습한 도매상 선택 로직

        우선순위:
        1. 재고 (있는 곳 우선)
        2. 배송 (need_by_time 충족 가능한 곳)
        3. 한도 (여유 있는 곳)
        4. 선호도 (과거 패턴)
        """
        candidates = []

        for ws in ['geoyoung', 'sooin', 'baekje']:
            score = 0

            # 1. 재고 체크
            if has_stock(ws, drug_code, quantity):
                score += 100
            else:
                continue  # 재고 없으면 제외

            # 2. 배송 시간 체크
            if need_by_time:
                delivery = get_next_delivery(ws, need_by_time)
                if delivery['can_deliver']:
                    score += 50
                else:
                    score -= 30  # 감점

            # 3. 한도 체크
            limit_usage = get_limit_usage(ws)
            if limit_usage < 0.9:
                score += 30
            elif limit_usage >= 1.0:
                score -= 50  # 한도 초과

            # 4. 학습된 선호도
            score += ai_model.preference_score(ws, drug_code) * 20

            candidates.append((ws, score))

        return max(candidates, key=lambda x: x[1])[0]

### 4.4 주문 타이밍 학습

    학습 데이터:
    - 하루 중 주문 시점 (오전/오후)
    - 요일별 주문 패턴
    - 배송 마감 시간 전 주문 여부

    학습 목표:
    - 최적 주문 시점 파악
    - 배송 마감 놓치지 않기
    - 분할 주문 (오전/오후) 패턴

## 5. 핵심 기능 설계

### 5.1 선주문 반영 시스템

목적: 같은 날 이미 주문한 품목 자동 차감

    def calculate_order_qty(drug_code, usage_qty, current_stock):
        # 오늘 "실제로" 주문 완료된 수량 조회
        today_ordered = get_today_orders(drug_code)

        # 필요량 = 사용량 - 현재고 - 선주문량
        needed = usage_qty - current_stock - today_ordered

        if needed > 0:
            return calculate_spec_qty(needed)
        return 0

⚠️ 핵심: 실제 주문만 카운트

    SELECT SUM(oi.total_dose) as today_ordered
    FROM order_items oi
    JOIN orders o ON oi.order_id = o.id
    WHERE oi.drug_code = ?
      AND o.order_date = DATE('now')
      AND o.is_dry_run = 0              -- dry_run 제외!
      AND oi.status IN ('success', 'submitted')

### 5.2 도매상 한도 관리

목적: 월별 거래 한도 설정 및 자동 분배

    [한도 도달 시 동작]
    1. 90% 도달 → 경고 알림
    2. 100% 도달 → 다른 도매상으로 자동 전환
    3. 장바구니 단계에서 미리 분류

### 5.3 배송 스케줄 기반 주문

목적: 주문 마감시간 + 배송 도착시간 분리 관리

    AI 판단 예시:

    현재 오전 11시, "오후 3시에 필요"

    → 지오영 오전: 10시 마감 지남 ❌
    → 지오영 오후: 13시 마감 → 15:00 도착 (⚠️ 딱 맞음)
    → 수인: 13시 마감 → 14:30 도착 (✅ 여유)
    → 백제: 내일 도착 ❌

    결론: 수인 추천 (14:30 도착, 30분 여유)

### 5.4 주문 실패 시 재시도

    시나리오 1: 재고 없음
    - A도매상 재고 0 → B도매상 검색 → 재고 있으면 B로 주문

    시나리오 2: 주문 오류
    - A도매상 API 오류 → 3회 재시도 → 실패 시 B도매상

    시나리오 3: 부분 성공
    - 10개 품목 중 7개 성공, 3개 실패
    - 실패한 3개 → B도매상으로 자동 재시도

    [리포트]
    - 최종 주문 결과 리포트
    - 알림: "A도매상 품절로 B도매상으로 변경됨"

## 6. 데이터 모델

### 6.1 핵심 테이블 (기존)

    -- 주문 컨텍스트 (AI 학습용)
    CREATE TABLE order_context (
        id INTEGER PRIMARY KEY,
        order_item_id INTEGER,

        -- 약품 정보
        drug_code TEXT,
        product_name TEXT,

        -- 주문 시점 상황
        stock_at_order INTEGER,
        usage_1d INTEGER,
        usage_7d INTEGER,
        usage_30d INTEGER,
        avg_daily_usage REAL,

        -- 주문 결정
        ordered_spec TEXT,
        ordered_qty INTEGER,
        wholesaler_id TEXT,

        -- 선택지 정보 (AI 학습용)
        available_specs JSON,
        spec_stocks JSON,
        selection_reason TEXT,

        -- 예측 vs 실제
        predicted_days_coverage REAL,
        actual_days_to_reorder INTEGER,

        -- 결과 평가
        was_optimal BOOLEAN,
        stockout_occurred BOOLEAN,

        created_at TIMESTAMP
    );

### 6.2 신규 테이블

    -- 도매상 한도 관리
    CREATE TABLE wholesaler_limits (
        id INTEGER PRIMARY KEY,
        wholesaler_id TEXT NOT NULL,
        monthly_limit INTEGER DEFAULT 0,
        warning_threshold REAL DEFAULT 0.9,
        priority INTEGER DEFAULT 1,
        is_active INTEGER DEFAULT 1,
        created_at TIMESTAMP,
        FOREIGN KEY (wholesaler_id) REFERENCES wholesalers(id)
    );

    -- 배송 스케줄
    CREATE TABLE delivery_schedules (
        id INTEGER PRIMARY KEY,
        wholesaler_id TEXT NOT NULL,
        delivery_seq INTEGER NOT NULL,
        delivery_name TEXT,
        order_cutoff_time TEXT NOT NULL,      -- 주문 마감 (HH:MM)
        delivery_days_offset INTEGER DEFAULT 0, -- 0=당일, 1=익일
        delivery_arrival_time TEXT NOT NULL,   -- 도착 예정 (HH:MM)
        weekdays TEXT,                         -- JSON [1,2,3,4,5]
        is_active INTEGER DEFAULT 1,
        UNIQUE(wholesaler_id, delivery_seq)
    );

    -- 실제 배송 스케줄 데이터
    INSERT INTO delivery_schedules VALUES
    ('geoyoung', 1, '오전배송', '10:00', 0, '11:30'),
    ('geoyoung', 2, '오후배송', '13:00', 0, '15:00'),
    ('sooin', 1, '오후배송', '13:00', 0, '14:30'),
    ('baekje', 1, '익일배송', '16:00', 1, '15:00');

    -- 월별 사용량 추적
    CREATE TABLE wholesaler_monthly_usage (
        id INTEGER PRIMARY KEY,
        wholesaler_id TEXT NOT NULL,
        year_month TEXT NOT NULL,
        total_orders INTEGER DEFAULT 0,
        total_amount INTEGER DEFAULT 0,
        UNIQUE(wholesaler_id, year_month)
    );

    -- 주문 재시도 로그
    CREATE TABLE order_fallback_log (
        id INTEGER PRIMARY KEY,
        order_item_id INTEGER NOT NULL,
        original_wholesaler TEXT NOT NULL,
        original_error TEXT,
        fallback_wholesaler TEXT NOT NULL,
        fallback_result TEXT,
        created_at TIMESTAMP
    );

### 6.3 기존 테이블 확장

    -- orders 테이블 확장
    ALTER TABLE orders ADD COLUMN is_dry_run INTEGER DEFAULT 0;

    -- order_items 테이블 확장
    ALTER TABLE order_items ADD COLUMN fallback_from_wholesaler TEXT;
    ALTER TABLE order_items ADD COLUMN prior_order_qty INTEGER DEFAULT 0;

## 7. API 설계

### 7.1 도매상 관리 API

엔드포인트 | 메서드 | 기능
--- | --- | ---
`/api/wholesaler/limits` | GET | 한도 조회
`/api/wholesaler/limits/{id}` | PUT | 한도 설정
`/api/wholesaler/schedules` | GET | 배송 스케줄
`/api/wholesaler/can-deliver-by` | POST | 배송 가능 여부

### 7.2 주문 API

엔드포인트 | 메서드 | 기능
--- | --- | ---
`/api/order/today/{drug_code}` | GET | 오늘 주문량
`/api/order/recommend-spec` | POST | 규격 추천
`/api/order/create` | POST | 주문 생성
`/api/order/submit` | POST | 주문 제출 (dry_run 지원)
`/api/order/retry` | POST | 실패 재시도

### 7.3 AI API

엔드포인트 | 메서드 | 기능
--- | --- | ---
`/api/ai/daily-analysis` | GET | 일일 분석
`/api/ai/recommendations` | GET | 주문 추천
`/api/ai/training-data` | GET | 학습 데이터
`/api/ai/patterns/{drug_code}` | GET | 패턴 분석

## 8. 자동화 레벨

### Level 0: 수동

- AI 추천만 제공
- 모든 주문은 수동 실행

### Level 1: 반자동

- AI가 주문 계획 생성
- 약사님 승인 후 자동 실행
- 알림: 승인 요청

### Level 2: 조건부 자동

- 신뢰도 높은 주문은 자동 실행
- 신뢰도 낮은 주문만 승인 요청
- 조건:
- 자주 주문하는 품목
- 금액 임계값 이하
- 긴급하지 않은 주문

### Level 3: 완전 자동

- 모든 주문 자동 실행
- 이상 상황만 알림
- 약사님은 대시보드로 모니터링

    def should_auto_execute(order_plan):
        level = settings.automation_level

        if level == 0:
            return False

        if level == 1:
            return False  # 항상 승인 필요

        if level == 2:
            conditions = [
                order_plan['confidence'] > 0.9,
                order_plan['estimated_cost'] < 100000,
                order_plan['drug_code'] in trusted_drugs,
                order_plan['urgency'] != 'critical'
            ]
            return all(conditions)

        if level == 3:
            return not is_anomaly(order_plan)

## 9. 알림 시스템

### 알림 유형

유형 | 조건 | 우선순위
--- | --- | ---
승인 요청 | 자동 실행 안 되는 주문 | 높음
주문 완료 | 자동 주문 실행됨 | 보통
한도 경고 | 90% 도달 | 높음
품절 긴급 | 재고 0, 당일 필요 | 긴급
배송 마감 | 마감 30분 전 | 높음
도매상 변경 | 품절로 다른 도매상 | 보통

### 알림 예시

    📦 주문 승인 요청

    약품: 콩코르정 2.5mg
    현재고: 45개 (3일치)
    추천 주문: 300T x 2박스
    도매상: 지오영 (점심배송 11:00 마감)
    예상 금액: 72,000원

    [승인] [수정] [거절]

    ⚠️ 배송 마감 알림

    지오영 오후배송 마감 30분 전!
    현재 장바구니: 5품목

    13:00까지 주문하지 않으면 다음 배송은 내일입니다.

    [지금 주문] [나중에]

## 10. 개발 로드맵

### Phase 1: 핵심 기반 (1주차)

- [x] 도매상 API 연동 (3개)
- [x] 주문 DB 스키마
- [x] dry_run 테스트 모드
- [ ] 선주문 조회 API
- [ ] 도매상 한도 테이블
- [ ] 배송 스케줄 테이블

### Phase 2: 주문 자동화 (2주차)

- [ ] 규격 추천 API
- [ ] 한도 체크 로직
- [ ] 주문 재시도 로직
- [ ] 장바구니 동기화

### Phase 3: UI 개선 (2주차)

- [ ] 한도 대시보드
- [ ] 주문 화면 (선주문 반영)
- [ ] 배송 스케줄 표시

### Phase 4: AI 학습 (3주차)

- [ ] 피드백 루프 구현
- [ ] 주문 평가 시스템
- [ ] 패턴 학습 (규격, 도매상)
- [ ] 수요 예측 (단순 이동평균)

### Phase 5: 완전 자동화 (4주차~)

- [ ] Level 1 자동화
- [ ] 알림 시스템 연동
- [ ] Level 2 조건부 자동화
- [ ] 모니터링 대시보드

## 11. 성공 지표 (KPI)

지표 | 현재 | 목표
--- | --- | ---
주문 소요 시간 | 30분/일 | 0분 (자동)
품절 발생률 | 5% | <1%
재고 회전율 | - | +20%
배송 마감 놓침 | 가끔 | 0회
주문 비용 절감 | - | 5-10% (OTC)

## 📚 참고 문서

- 어제 작성 (AI 비전/모델): `docs/AI_ERP_AUTO_ORDER_SYSTEM.md`
- 오늘 작성 (API/DB 상세): `docs/자동발주시스템_고도화_기획서_v2.md`
- 도매상 API 분석: `docs/GEOYOUNG_API_REVERSE_ENGINEERING.md`
- Rx 사용량 가이드: `docs/RX_USAGE_GEOYOUNG_GUIDE.md`

> 🐉 용림: 이 문서는 AI_ERP_AUTO_ORDER_SYSTEM.md(비전/AI모델)와
> 자동발주시스템_고도화_기획서_v2.md(API/DB상세)를 통합한 마스터 기획서입니다.