mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 20:46:24 +00:00
165 lines
6.5 KiB
Plaintext
165 lines
6.5 KiB
Plaintext
@startuml participation-당첨자추첨
|
|
!theme mono
|
|
|
|
title Participation Service - 당첨자 추첨 내부 시퀀스
|
|
|
|
actor "사장님" as Owner
|
|
participant "API Gateway" as Gateway
|
|
participant "ParticipationController" as Controller
|
|
participant "ParticipationService" as Service
|
|
participant "LotteryAlgorithm" as Lottery
|
|
participant "ParticipantRepository" as Repo
|
|
participant "DrawLogRepository" as LogRepo
|
|
database "Participation DB" as DB
|
|
|
|
== UFR-PART-030: 당첨자 추첨 ==
|
|
|
|
Owner -> Gateway: POST /api/v1/events/{eventId}/draw-winners\n{winnerCount, visitBonus, algorithm}
|
|
activate Gateway
|
|
|
|
Gateway -> Gateway: JWT 토큰 검증\n- 토큰 유효성 확인\n- 사장님 권한 확인
|
|
|
|
alt JWT 검증 실패
|
|
Gateway --> Owner: 401 Unauthorized
|
|
deactivate Gateway
|
|
else JWT 검증 성공
|
|
|
|
Gateway -> Controller: POST /participations/draw-winners\n{eventId, winnerCount, visitBonus}
|
|
activate Controller
|
|
|
|
Controller -> Controller: 요청 데이터 유효성 검증\n- eventId 필수\n- winnerCount > 0\n- winnerCount <= 참여자 수
|
|
|
|
alt 유효성 검증 실패
|
|
Controller --> Gateway: 400 Bad Request
|
|
Gateway --> Owner: 400 Bad Request
|
|
deactivate Controller
|
|
deactivate Gateway
|
|
else 유효성 검증 성공
|
|
|
|
Controller -> Service: drawWinners(eventId, winnerCount, visitBonus)
|
|
activate Service
|
|
|
|
Service -> Service: 이벤트 상태 확인\n- 이벤트 종료 여부\n- 이미 추첨 완료 여부
|
|
|
|
Service -> LogRepo: findByEventId(eventId)
|
|
activate LogRepo
|
|
LogRepo -> DB: 추첨 로그 조회\n(이벤트ID로 조회)
|
|
activate DB
|
|
DB --> LogRepo: 추첨 로그 조회
|
|
deactivate DB
|
|
LogRepo --> Service: Optional<DrawLog>
|
|
deactivate LogRepo
|
|
|
|
alt 이미 추첨 완료
|
|
Service --> Controller: AlreadyDrawnException
|
|
Controller --> Gateway: 409 Conflict\n{message: "이미 추첨이 완료된 이벤트입니다"}
|
|
Gateway --> Owner: 409 Conflict
|
|
deactivate Service
|
|
deactivate Controller
|
|
deactivate Gateway
|
|
else 추첨 가능 상태
|
|
|
|
Service -> Repo: findAllByEventIdAndIsWinner(eventId, false)
|
|
activate Repo
|
|
Repo -> DB: 미당첨 참여자 목록 조회\n(이벤트ID로 당첨되지 않은\n참여자 전체 조회,\n참여일시 오름차순 정렬)
|
|
activate DB
|
|
DB --> Repo: 전체 참여자 목록
|
|
deactivate DB
|
|
Repo --> Service: List<Participant>
|
|
deactivate Repo
|
|
|
|
alt 참여자 수 부족
|
|
Service --> Controller: InsufficientParticipantsException
|
|
Controller --> Gateway: 400 Bad Request\n{message: "참여자 수가 부족합니다"}
|
|
Gateway --> Owner: 400 Bad Request
|
|
deactivate Service
|
|
deactivate Controller
|
|
deactivate Gateway
|
|
else 추첨 진행
|
|
|
|
Service -> Lottery: executeLottery(participants, winnerCount, visitBonus)
|
|
activate Lottery
|
|
|
|
note right of Lottery
|
|
추첨 알고리즘:
|
|
시간 복잡도: O(n log n)
|
|
공간 복잡도: O(n)
|
|
|
|
1. 난수 생성 (Crypto.randomBytes)
|
|
2. 매장 방문 가산점 적용 (옵션)
|
|
- 방문 고객: 가중치 2배
|
|
- 비방문 고객: 가중치 1배
|
|
3. Fisher-Yates Shuffle
|
|
- 가중치 기반 확률 분포
|
|
- 무작위 섞기
|
|
4. 상위 N명 선정
|
|
end note
|
|
|
|
Lottery -> Lottery: Step 1: 난수 시드 생성\n- Crypto.randomBytes(32)\n- 예측 불가능한 난수 보장
|
|
|
|
Lottery -> Lottery: Step 2: 가산점 적용\n- visitBonus = true일 경우\n- 매장 방문 경로 참여자 가중치 증가
|
|
|
|
Lottery -> Lottery: Step 3: Fisher-Yates Shuffle\n- 가중치 기반 확률 분포\n- O(n) 시간 복잡도
|
|
|
|
Lottery -> Lottery: Step 4: 당첨자 선정\n- 상위 winnerCount명 추출
|
|
|
|
Lottery --> Service: List<Participant> 당첨자 목록
|
|
deactivate Lottery
|
|
|
|
Service -> Service: DB 트랜잭션 시작
|
|
|
|
alt DB 저장 실패 시
|
|
note right of Service
|
|
트랜잭션 롤백 처리:
|
|
- 당첨자 업데이트 취소
|
|
- 추첨 로그 저장 취소
|
|
- 재시도 가능 상태 유지
|
|
end note
|
|
end
|
|
|
|
Service -> Repo: updateWinners(winnerIds)
|
|
activate Repo
|
|
Repo -> DB: 당첨자 정보 업데이트\n(당첨 여부를 true로,\n당첨 일시를 현재 시각으로 설정,\n대상: 선정된 참여자ID 목록)
|
|
activate DB
|
|
DB --> Repo: 업데이트 완료
|
|
deactivate DB
|
|
Repo --> Service: 업데이트 건수
|
|
deactivate Repo
|
|
|
|
Service -> Service: DrawLog 엔티티 생성\n- drawLogId (UUID)\n- eventId\n- drawMethod: "RANDOM"\n- algorithm: "FISHER_YATES_SHUFFLE"\n- visitBonusApplied\n- winnerCount\n- drawnAt (현재시각)
|
|
|
|
Service -> LogRepo: save(drawLog)
|
|
activate LogRepo
|
|
LogRepo -> DB: 추첨 로그 저장\n(추첨로그ID, 이벤트ID,\n추첨방법, 알고리즘,\n가산점적용여부, 당첨인원,\n추첨일시 저장)
|
|
activate DB
|
|
note right of DB
|
|
추첨 로그 저장:
|
|
- 추첨 일시 기록
|
|
- 알고리즘 버전 기록
|
|
- 가산점 적용 여부
|
|
- 감사 추적 목적
|
|
end note
|
|
DB --> LogRepo: 로그 저장 완료
|
|
deactivate DB
|
|
LogRepo --> Service: DrawLog 엔티티
|
|
deactivate LogRepo
|
|
|
|
Service -> Service: DB 트랜잭션 커밋
|
|
|
|
Service --> Controller: DrawWinnersResponse\n{당첨자목록, 추첨로그ID}
|
|
deactivate Service
|
|
|
|
Controller --> Gateway: 200 OK\n{winners[], drawLogId, message}
|
|
deactivate Controller
|
|
|
|
Gateway --> Owner: 200 OK
|
|
deactivate Gateway
|
|
|
|
Owner -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 테이블\n- 재추첨 버튼\n- 추첨 완료 메시지
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
@enduml
|