@startuml
!theme mono

title Participation Service ERD

' 스타일 정의
skinparam linetype ortho
skinparam roundcorner 10
skinparam class {
    BackgroundColor White
    BorderColor Black
    ArrowColor Black
}

' 참여자 테이블
entity "participants" as participants {
    **id : BIGSERIAL <<PK>>**
    --
    participant_id : VARCHAR(50) <<UK>>
    event_id : VARCHAR(50) <<FK>>
    name : VARCHAR(100)
    phone_number : VARCHAR(20)
    email : VARCHAR(100)
    channel : VARCHAR(50)
    store_visited : BOOLEAN
    bonus_entries : INTEGER
    agree_marketing : BOOLEAN
    agree_privacy : BOOLEAN
    is_winner : BOOLEAN
    winner_rank : INTEGER
    won_at : TIMESTAMP
    created_at : TIMESTAMP
    updated_at : TIMESTAMP
    --
    **Indexes:**
    idx_participants_event_created
    idx_participants_event_winner
    idx_participants_event_store
    --
    **Constraints:**
    uk_participant_id UNIQUE
    uk_event_phone UNIQUE (event_id, phone_number)
    chk_bonus_entries (1 <= bonus_entries <= 3)
    chk_channel IN ('WEB', 'MOBILE', 'INSTORE')
    chk_winner_rank (winner_rank IS NULL OR > 0)
}

' 추첨 이력 테이블
entity "draw_logs" as draw_logs {
    **id : BIGSERIAL <<PK>>**
    --
    event_id : VARCHAR(50) <<UK>>
    total_participants : INTEGER
    winner_count : INTEGER
    apply_store_visit_bonus : BOOLEAN
    algorithm : VARCHAR(50)
    drawn_at : TIMESTAMP
    drawn_by : VARCHAR(100)
    created_at : TIMESTAMP
    updated_at : TIMESTAMP
    --
    **Indexes:**
    idx_draw_logs_event
    idx_draw_logs_drawn_at
    --
    **Constraints:**
    uk_draw_event UNIQUE (event_id)
    chk_winner_count (winner_count > 0)
    chk_total_participants (total_participants >= winner_count)
    chk_algorithm IN ('RANDOM', 'WEIGHTED')
}

' 관계 정의
participants "N" -- "1" draw_logs : event_id

' 노트
note right of participants
    **참여자 관리**
    - 중복 참여 방지 (event_id + phone_number)
    - 매장 방문 보너스 응모권 관리
    - 당첨자 상태 관리

    **보너스 응모권 계산**
    - 기본: 1개
    - 매장 방문 시: 3개 (+2 보너스)

    **participant_id 형식**
    EVT{eventId}-{YYYYMMDD}-{SEQ}
    예시: EVT123-20251029-001
end note

note right of draw_logs
    **추첨 이력 관리**
    - 이벤트당 1회만 추첨 가능
    - 재추첨 방지
    - 감사 추적 (drawn_by, drawn_at)

    **추첨 알고리즘**
    - RANDOM: 단순 무작위 추첨
    - WEIGHTED: 보너스 응모권 적용 추첨
end note

' 캐시 정보 노트
note bottom of participants
    **Redis 캐시 키 구조**

    1. 참여 세션 정보
       Key: participation:session:{eventId}:{phoneNumber}
       TTL: 10분
       용도: 중복 참여 방지

    2. 추첨 결과 임시 저장
       Key: participation:draw:{eventId}
       TTL: 1시간
       용도: 빠른 조회

    3. 이벤트별 참여자 카운트
       Key: participation:count:{eventId}
       TTL: 5분
       용도: 실시간 집계
end note

' 외부 참조 노트
note top of participants
    **외부 서비스 참조 (캐시 기반)**

    - event_id: Event Service 이벤트 ID
    - 직접 FK 관계 없음 (마이크로서비스 독립성)
    - Redis 캐시로 이벤트 정보 참조
end note

@enduml
