Skip to content

Commit

Permalink
[Feat] 선착순 당첨 내역을 조회하는 API 구현 (#189)
Browse files Browse the repository at this point in the history
* [Infra] CI/CD test (#42)

* infra: 빌드 테스트 yml 작성

* infra: DB 정보 추가

* infra: ssh-agent 버전 변경

* infra: known_hosts 추가

* infra: db port 변경

* infra: database test 설정 변경

* infra: DB 환경변수 설정 및 application.yml 생성

* infra: application.yml 동적 생성 스크립트 수정

* infra: 레디스 설정 추가

* infra: redis test 추가

* infra: redis 버전 변경

* infra: redis cli 설치

* infra: application.yml 위치 및 내용 확인

* infra: Github Actions 환경변수에 REDIS_HOST, REDIS_PORT 추가

* infra: 환경변수 확인 추가

* infra: zip file 만들기 추가, AWS credentials 추가

* infra: 환경변수 이름 변경

- ARN -> AWS_ARN

* infra: s3 bucket에 업로드 추가

* infra: code deploy 추가

* infra: code deploy 수정

* infra: code deploy 수정

* infra: appspec.yml 작성

* infra: application.yml 생성 경로 변경

* infra: application.yml 확인 스크립트 삭제

* infra: application.yml 생성 스크립트 수정

* infra: application-prod.yml 추가

* infra: appspec.yml 수정, 배포를 위한 sh파일 추가

* infra: deploy.yml 이름 변경

- test_deploy -> deploy

* infra: body = null 설정

* infra: develop에 머지되었을 때만 발동하도록 수정

* feat: draw_rank column 이름 수정

* Infra: environment 삭제

* [Infra] CI CD test 3 (#45)

* infra: 빌드 테스트 yml 작성

* infra: DB 정보 추가

* infra: ssh-agent 버전 변경

* infra: known_hosts 추가

* infra: db port 변경

* infra: database test 설정 변경

* infra: DB 환경변수 설정 및 application.yml 생성

* infra: application.yml 동적 생성 스크립트 수정

* infra: 레디스 설정 추가

* infra: redis test 추가

* infra: redis 버전 변경

* infra: redis cli 설치

* infra: application.yml 위치 및 내용 확인

* infra: Github Actions 환경변수에 REDIS_HOST, REDIS_PORT 추가

* infra: 환경변수 확인 추가

* infra: zip file 만들기 추가, AWS credentials 추가

* infra: 환경변수 이름 변경

- ARN -> AWS_ARN

* infra: s3 bucket에 업로드 추가

* infra: code deploy 추가

* infra: code deploy 수정

* infra: code deploy 수정

* infra: appspec.yml 작성

* infra: application.yml 생성 경로 변경

* infra: application.yml 확인 스크립트 삭제

* infra: application.yml 생성 스크립트 수정

* infra: application-prod.yml 추가

* infra: appspec.yml 수정, 배포를 위한 sh파일 추가

* infra: deploy.yml 이름 변경

- test_deploy -> deploy

* infra: body = null 설정

* infra: develop에 머지되었을 때만 발동하도록 수정

* feat: draw_rank column 이름 수정

* Infra: environment 삭제

* Infra: environment 삭제

* config: jwt 속성을 yml에 설정

* rebase: 원본 develop 브랜치와 병합

* doc: jacoco 파일 생성

* feat: 선착순 이벤트 당첨 기록 응답 Dto 클래스

* chore: 패키지 변경

* feat: winningDate값 바인딩

* chore: 패키지 변경

* refactor: 변수 타입 변경

* feat: 선착순 당첨 기록을 처리하는 메서드 구현

* feat: 선착순 당첨 기록 응답을 반환하는 메서드 구현

* feat: 인수로 넘어온 선착순 설정 정보를 바인딩하는 메서드 구현

* chore: 패키지 변경

* refactor: redis prefix 상수 변경

* fix: 퀴즈 힌트 조회 로직 수정

* refactor: 메서드 변경

* feat: timeformatter 추가

* feat: entity에 변수 추가

* feat: 선착순 repository 메서드 추가

* chore: jacoco 파일 삭제

---------

Co-authored-by: DrRivaski <[email protected]>
Co-authored-by: hyeokson <[email protected]>
  • Loading branch information
3 people authored Aug 21, 2024
1 parent a87831c commit 189a28d
Show file tree
Hide file tree
Showing 16 changed files with 159 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.softeer.backend.fo_domain.fcfs.controller;

import com.softeer.backend.fo_domain.fcfs.dto.FcfsHistoryResponseDto;
import com.softeer.backend.fo_domain.fcfs.dto.FcfsPageResponseDto;
import com.softeer.backend.fo_domain.fcfs.dto.FcfsRequestDto;
import com.softeer.backend.fo_domain.fcfs.dto.result.FcfsResult;
import com.softeer.backend.fo_domain.fcfs.dto.result.FcfsResultResponseDto;
import com.softeer.backend.fo_domain.fcfs.service.FcfsService;
import com.softeer.backend.global.annotation.AuthInfo;
import com.softeer.backend.global.common.response.ResponseDto;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -63,5 +62,13 @@ public ResponseDto<FcfsResultResponseDto> handleFcfs(@Parameter(hidden = true) H
return ResponseDto.onSuccess(fcfsResultResponseDto);
}

@GetMapping("/fcfs/history")
public ResponseDto<FcfsHistoryResponseDto> getFcfsHistory(@Parameter(hidden = true) @AuthInfo Integer userId){

FcfsHistoryResponseDto fcfsHistoryResponseDto = fcfsService.getFcfsHistory(userId);

return ResponseDto.onSuccess(fcfsHistoryResponseDto);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDate;
import java.time.LocalDateTime;

/**
Expand Down Expand Up @@ -38,8 +39,7 @@ public class Fcfs {
@Column(name = "code")
private String code;

@CreatedDate
@Column(name = "winning_date", nullable = false)
private LocalDateTime winningDate;
private LocalDate winningDate;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.softeer.backend.fo_domain.fcfs.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;

import java.time.LocalDate;
import java.util.List;

/**
* 선착순 이벤트 당첨 기록 응답 Dto 클래스
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PUBLIC)
@Builder
@Getter
@Setter
public class FcfsHistoryResponseDto {

@JsonProperty("isFcfsWin")
private boolean isFcfsWin;

private List<FcfsHistory> fcfsHistoryList;

@Getter
@AllArgsConstructor
@Builder
public static class FcfsHistory {

private String barcode;

private String fcfsCode;

@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate winningDate;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ public interface FcfsRepository extends JpaRepository<Fcfs, Integer> {
@Query("SELECT f FROM Fcfs f JOIN FETCH f.user WHERE f.round = :round")
List<Fcfs> findFcfsWithUser(@Param("round") int round);

List<Fcfs> findByUserIdOrderByWinningDateAsc(Integer userId);

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.softeer.backend.fo_domain.fcfs.service;

import com.softeer.backend.fo_domain.draw.service.DrawSettingManager;
import com.softeer.backend.fo_domain.fcfs.domain.Fcfs;
import com.softeer.backend.fo_domain.fcfs.dto.*;
import com.softeer.backend.fo_domain.fcfs.dto.result.FcfsFailResult;
import com.softeer.backend.fo_domain.fcfs.dto.result.FcfsResultResponseDto;
import com.softeer.backend.fo_domain.fcfs.dto.result.FcfsSuccessResult;
import com.softeer.backend.fo_domain.fcfs.exception.FcfsException;
import com.softeer.backend.fo_domain.fcfs.repository.FcfsRepository;
import com.softeer.backend.global.annotation.EventLock;
import com.softeer.backend.global.common.code.status.ErrorStatus;
import com.softeer.backend.global.common.constant.RedisKeyPrefix;
Expand All @@ -20,9 +22,15 @@
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.toList;

/**
* 선착순 관련 이벤트를 처리하는 클래스
*/
Expand All @@ -40,6 +48,8 @@ public class FcfsService {
private final RandomCodeUtil randomCodeUtil;
private final StaticResourceUtil staticResourceUtil;

private final FcfsRepository fcfsRepository;

/**
* 선착순 페이지에 필요한 정보를 반환하는 메서드
*/
Expand Down Expand Up @@ -235,4 +245,53 @@ public FcfsFailResult getFcfsFailResult(Map<String, String> textContentMap) {
.build();
}

/**
* 선착순 당첨 기록 응답을 반환하는 메서드
*/
public FcfsHistoryResponseDto getFcfsHistory(int userId){
fcfsRepository.findByUserIdOrderByWinningDateAsc(userId);
List<FcfsHistoryResponseDto.FcfsHistory> fcfsHistoryList = new ArrayList<>();

Map<String, String> s3ContentMap = staticResourceUtil.getS3ContentMap();

LocalDate now = LocalDate.now();
Integer round = fcfsSettingManager.getFcfsRoundForHistory(now);
if(round == null)
round = fcfsSettingManager.getFcfsRoundForHistory(now.minusDays(1));
if(round != null
&& fcfsRedisUtil.isValueInIntegerSet(RedisKeyPrefix.FCFS_USERID_PREFIX.getPrefix() + round, userId)){
Map<String, Integer> fcfsMap = fcfsRedisUtil.getHashEntries(RedisKeyPrefix.FCFS_CODE_USERID_PREFIX.getPrefix() + round);

for (Map.Entry<String, Integer> entry : fcfsMap.entrySet()) {
if (entry.getValue().equals(userId)) {
String fcfsCode = entry.getKey();

fcfsHistoryList.add(FcfsHistoryResponseDto.FcfsHistory.builder()
.barcode(s3ContentMap.get(S3FileName.BARCODE_IMAGE.name()))
.fcfsCode(fcfsCode)
.winningDate(now)
.build());

break;
}
}
}

List<Fcfs> fcfsList = fcfsRepository.findByUserIdOrderByWinningDateAsc(userId);
fcfsHistoryList.addAll(fcfsList.stream()
.map((fcfs) ->
FcfsHistoryResponseDto.FcfsHistory.builder()
.barcode(s3ContentMap.get(S3FileName.BARCODE_IMAGE.name()))
.fcfsCode(fcfs.getCode())
.winningDate(fcfs.getWinningDate())
.build()
).toList());

return FcfsHistoryResponseDto.builder()
.isFcfsWin(!fcfsHistoryList.isEmpty())
.fcfsHistoryList(fcfsHistoryList)
.build();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void loadInitialData() {
/**
* 인수로 넘어온 선착순 설정 정보를 바인딩하는 메서드
*/
public void setFcfsSettingList(List<FcfsSetting> fcfsSettings){
public void setFcfsSettingList(List<FcfsSetting> fcfsSettings) {

fcfsSettings.forEach((fcfsSetting) -> {
fcfsSettingList.set(fcfsSetting.getRound() - 1, FcfsSettingDto.builder()
Expand Down Expand Up @@ -110,19 +110,19 @@ public int getRoundForScheduler(LocalDate localDate) {
/**
* 선착순 이벤트 당첨 가능한 인원수를 반환하는 메서드
*/
public int getFcfsWinnerNum(){
public int getFcfsWinnerNum() {
return fcfsSettingList.get(0).getWinnerNum();
}

/**
* 현재 시간을 기준으로 선착순 이벤트가 활성화 되어 있는지를 반환하는 메서드
*/
public boolean isFcfsEntryAvailable(LocalDateTime now){
for(FcfsSettingDto fcfsSettingDto : fcfsSettingList){
public boolean isFcfsEntryAvailable(LocalDateTime now) {
for (FcfsSettingDto fcfsSettingDto : fcfsSettingList) {
LocalDateTime startTime = fcfsSettingDto.getStartTime();
LocalDateTime endTime = fcfsSettingDto.getEndTime();

if((now.isEqual(startTime) || now.isAfter(startTime))
if ((now.isEqual(startTime) || now.isAfter(startTime))
&& (now.isEqual(endTime) || now.isBefore(endTime))) {
return true;
}
Expand All @@ -133,13 +133,13 @@ public boolean isFcfsEntryAvailable(LocalDateTime now){
/**
* 현재 시간에 해당하는 선착순 이벤트의 round값을 반환하는 메서드
*/
public Integer getFcfsRound(LocalDateTime now){
public Integer getFcfsRound(LocalDateTime now) {

for(FcfsSettingDto fcfsSettingDto : fcfsSettingList){
for (FcfsSettingDto fcfsSettingDto : fcfsSettingList) {
LocalDateTime startTime = fcfsSettingDto.getStartTime();
LocalDateTime endTime = fcfsSettingDto.getEndTime();

if((now.isEqual(startTime) || now.isAfter(startTime))
if ((now.isEqual(startTime) || now.isAfter(startTime))
&& (now.isEqual(endTime) || now.isBefore(endTime))) {
return fcfsSettingDto.getRound();
}
Expand All @@ -150,16 +150,28 @@ public Integer getFcfsRound(LocalDateTime now){
/**
* 현재 시간을 기준으로 다음 선착순 이벤트의 시작 시간을 반환하는 메서드
*/
public LocalDateTime getNextFcfsTime(LocalDateTime now){
public LocalDateTime getNextFcfsTime(LocalDateTime now) {

for(FcfsSettingDto fcfsSettingDto : fcfsSettingList){
for (FcfsSettingDto fcfsSettingDto : fcfsSettingList) {
LocalDateTime startTime = fcfsSettingDto.getStartTime();

if(now.isBefore(startTime)) {
if (now.isBefore(startTime)) {
return startTime;
}
}
return null;
}

public Integer getFcfsRoundForHistory(LocalDate now) {

for (FcfsSettingDto fcfsSettingDto : fcfsSettingList) {
LocalDateTime startTime = fcfsSettingDto.getStartTime();

if (now.isEqual(startTime.toLocalDate())) {
return fcfsSettingDto.getRound();
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ public String getHint(){
if (fcfsSettingDto != null) {
LocalDateTime endTime = fcfsSettingDto.getEndTime();

// localDate가 startDate의 하루 다음날과 같은지 확인
if (endTime.isBefore(now)) {
if (now.isBefore(endTime)) {
return quizList.get(i).getHint();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.softeer.backend.fo_domain.mainpage.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;

import java.time.LocalDateTime;
Expand All @@ -26,6 +27,9 @@ public class MainPageEventInfoResponseDto {

private String fcfsHint;

@JsonProperty("isFcfsAvailable")
private boolean isFcfsAvailable;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime fcfsStartTime;
private LocalDateTime nextFcfsStartTime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
@RequiredArgsConstructor
public class MainPageService {
private final DateTimeFormatter eventTimeFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");
private final DateTimeFormatter fcfsTimeFormatter = DateTimeFormatter.ofPattern("a h", Locale.KOREAN);
private final DateTimeFormatter fcfsTimeFormatter = DateTimeFormatter.ofPattern("a h시", Locale.KOREAN);
private final DateTimeFormatter fcfsTimeMinFormatter = DateTimeFormatter.ofPattern("a h시 m분", Locale.KOREAN);
private final DecimalFormat decimalFormat = new DecimalFormat("#,###");

private final EventLockRedisUtil eventLockRedisUtil;
Expand Down Expand Up @@ -104,20 +105,28 @@ public MainPageEventInfoResponseDto getEventPageInfo() {

int remainDrawCount = totalDrawWinner - (int) drawRepository.count();

String fcfsTime = "";
if(firstFcfsSetting.getStartTime().getMinute() != 0){
fcfsTime = firstFcfsSetting.getStartTime().format(fcfsTimeFormatter);
}
else
fcfsTime = firstFcfsSetting.getStartTime().format(fcfsTimeMinFormatter);

return MainPageEventInfoResponseDto.builder()
.startDate(drawSettingManager.getStartDate().format(eventTimeFormatter))
.endDate(drawSettingManager.getEndDate().format(eventTimeFormatter))
.fcfsInfo(staticResourceUtil.format(textContentMap.get(StaticTextName.FCFS_INFO.name()),
staticResourceUtil.getKoreanDayOfWeek(firstFcfsSetting.getStartTime().getDayOfWeek()),
staticResourceUtil.getKoreanDayOfWeek(secondFcfsSetting.getStartTime().getDayOfWeek()),
firstFcfsSetting.getStartTime().format(fcfsTimeFormatter),
fcfsTime,
firstFcfsSetting.getWinnerNum()))
.totalDrawWinner(staticResourceUtil.format(
textContentMap.get(StaticTextName.TOTAL_DRAW_WINNER.name()), decimalFormat.format(totalDrawWinner)))
.remainDrawCount(staticResourceUtil.format(
textContentMap.get(StaticTextName.REMAIN_DRAW_COUNT.name()), decimalFormat.format(remainDrawCount)))
.fcfsHint(quizManager.getHint())
.fcfsStartTime(fcfsSettingManager.getNextFcfsTime(LocalDateTime.now()))
.isFcfsAvailable(fcfsSettingManager.isFcfsEntryAvailable(LocalDateTime.now()))
.nextFcfsStartTime(fcfsSettingManager.getNextFcfsTime(LocalDateTime.now()))
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum RedisKeyPrefix {
DRAW_PARTICIPANT_COUNT_PREFIX("DRAW_PARTICIPANT_COUNT"),

// 사이트 방문자 수
TOTAL_VISITORS_COUNT_PREFIX("TOTAL_VISITORS_COUNT_");
TOTAL_VISITORS_COUNT_PREFIX("TOTAL_VISITORS_COUNT");


private final String prefix;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ protected void insertData() {
.user(user)
.round(round)
.code(code)
.winningDate(now.minusDays(1))
.build();

// 코드와 사용자 저장
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.softeer.backend.fo_domain.admin.service;
package com.softeer.backend.bo_domain.admin.service;

import com.softeer.backend.bo_domain.admin.domain.Admin;
import com.softeer.backend.bo_domain.admin.dto.login.AdminLoginRequestDto;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.softeer.backend.fo_domain.admin.service;
package com.softeer.backend.bo_domain.admin.service;

import com.softeer.backend.bo_domain.admin.dto.event.DrawEventTimeRequestDto;
import com.softeer.backend.bo_domain.admin.dto.event.EventPageResponseDto;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.softeer.backend.fo_domain.admin.service;
package com.softeer.backend.bo_domain.admin.service;

import com.softeer.backend.bo_domain.admin.dto.indicator.EventIndicatorResponseDto;
import com.softeer.backend.bo_domain.admin.service.IndicatorPageService;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.softeer.backend.fo_domain.admin.service;
package com.softeer.backend.bo_domain.admin.service;

import com.softeer.backend.bo_domain.admin.dto.winner.*;
import com.softeer.backend.bo_domain.admin.service.WinnerPageService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void testGetEventPageInfo() {
assertThat(response.getStartDate()).isEqualTo("2024.08.01");
assertThat(response.getEndDate()).isEqualTo("2024.08.31");
assertThat(response.getFcfsHint()).isEqualTo("퀴즈 힌트");
assertThat(response.getFcfsStartTime()).isEqualTo(LocalDateTime.of(2024, 8, 22, 11, 0));
assertThat(response.getNextFcfsStartTime()).isEqualTo(LocalDateTime.of(2024, 8, 22, 11, 0));
}

@Test
Expand Down

0 comments on commit 189a28d

Please sign in to comment.