Skip to content

Commit

Permalink
Merge branch 'develop' into fix/147
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeokson authored Aug 18, 2024
2 parents 034a92f + 60af745 commit bec7d76
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;

import java.time.LocalDateTime;

@Getter
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "draw_participation_info")
public class DrawParticipationInfo {
@Id
Expand All @@ -23,14 +25,9 @@ public class DrawParticipationInfo {
@Column(name = "draw_losing_count")
private Integer drawLosingCount;

@Column(name = "draw_participation_count")
private Integer drawParticipationCount;
@Column(name = "draw_attendance_count")
private Integer drawAttendanceCount;

@Builder
public DrawParticipationInfo(Integer userId, Integer drawWinningCount, Integer drawLosingCount, Integer drawParticipationCount) {
this.userId = userId;
this.drawWinningCount = drawWinningCount;
this.drawLosingCount = drawLosingCount;
this.drawParticipationCount = drawParticipationCount;
}
@Column(name = "last_attendance")
private LocalDateTime lastAttendance;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
package com.softeer.backend.fo_domain.draw.dto.main;

import lombok.AllArgsConstructor;
import com.softeer.backend.fo_domain.draw.dto.modal.WinModal;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
public class DrawMainFullAttendResponseDto extends DrawMainResponseDto {
private DrawMainFullAttendResponseDto.FullAttendModal fullAttendModal;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public static class FullAttendModal {
private String title; // 제목
private String subtitle; // 부제목
private String image; // 이미지 URL (S3 URL)
private String description; // 설명
}
private WinModal fullAttendModal;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.softeer.backend.fo_domain.draw.dto.modal;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class WinModal {
private String title; // 제목
private String subtitle; // 부제목
private String img; // 이미지 URL (S3 URL)
private String description; // 설명
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
package com.softeer.backend.fo_domain.draw.dto.participate;

import lombok.AllArgsConstructor;
import com.softeer.backend.fo_domain.draw.dto.modal.WinModal;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
public class DrawWinModalResponseDto extends DrawModalResponseDto {
private DrawWinModalResponseDto.WinModal winModal;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public static class WinModal {
private String title; // 제목
private String subtitle; // 부제목
private String img; // 이미지 URL (S3 URL)
private String description; // 설명
}
private WinModal winModal;
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
package com.softeer.backend.fo_domain.draw.dto.result;

import lombok.AllArgsConstructor;
import com.softeer.backend.fo_domain.draw.dto.modal.WinModal;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
public class DrawHistoryWinnerResponseDto extends DrawHistoryResponseDto {
private DrawHistoryWinnerResponseDto.WinModal winModal;

@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public static class WinModal {
private String title; // 제목
private String subtitle; // 부제목
private String img; // 이미지 URL (S3 URL)
private String description; // 설명
}
private WinModal winModal;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.softeer.backend.fo_domain.draw.interceptor;

import com.softeer.backend.fo_domain.draw.exception.DrawException;
import com.softeer.backend.fo_domain.draw.service.DrawSettingManager;
import com.softeer.backend.global.common.code.status.ErrorStatus;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.servlet.HandlerInterceptor;

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

@Component
@RequiredArgsConstructor
public class DrawTimeCheckInterceptor implements HandlerInterceptor {
private final DrawSettingManager drawSettingManager;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (CorsUtils.isPreFlightRequest(request))
return true;

if (!isAvailableTime()) {
throw new DrawException(ErrorStatus._BAD_REQUEST);
}

return true;
}

/**
* 참가 가능한 시간인지 확인
* @return 참가 가능하면 true, 불가능하면 false 반환
*/
private boolean isAvailableTime() {
LocalDateTime now = LocalDateTime.now();

return compareDate(now) && compareTime(now);
}

/**
* 날짜 비교
* @param now 현재시각
* @return 참가 가능한 날짜이면 true, 불가능하면 false 반환
*/
private boolean compareDate(LocalDateTime now) {
LocalDateTime startDateTime = drawSettingManager.getStartDate().atStartOfDay();
LocalDateTime endDateTime = drawSettingManager.getEndDate().atStartOfDay();

return now.isAfter(startDateTime) && now.isBefore(endDateTime);
}

/**
* 시간 비교
* @param now 현재 시각
* @return 참가 가능한 시간이면 true, 불가능하면 false 반환
*/
private boolean compareTime(LocalDateTime now) {
LocalDate nowDate = now.toLocalDate();
LocalDateTime startTimeAsDateTime = LocalDateTime.of(nowDate, drawSettingManager.getStartTime());
LocalDateTime endTimeAsDateTime = LocalDateTime.of(nowDate, drawSettingManager.getEndTime());

return (now.isAfter(startTimeAsDateTime) && now.isBefore(endTimeAsDateTime));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Optional;

@Repository
Expand All @@ -22,4 +23,19 @@ public interface DrawParticipationInfoRepository extends JpaRepository<DrawParti
@Transactional
@Query("UPDATE DrawParticipationInfo d SET d.drawLosingCount = d.drawLosingCount + 1 WHERE d.userId = :userId")
void increaseLoseCount(Integer userId);

@Modifying
@Transactional
@Query("UPDATE DrawParticipationInfo d SET d.drawAttendanceCount = d.drawAttendanceCount + 1 WHERE d.userId = :userId")
void increaseAttendanceCount(Integer userId);

@Modifying
@Transactional
@Query("UPDATE DrawParticipationInfo d SET d.drawAttendanceCount = 1 WHERE d.userId = :userId")
void setAttendanceCountToOne(Integer userId);

@Modifying
@Transactional
@Query("UPDATE DrawParticipationInfo d SET d.lastAttendance = :lastAttendance WHERE d.userId = :userId")
void setLastAttendance(Integer userId, LocalDateTime lastAttendance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Set;

@Service
Expand All @@ -44,19 +46,98 @@ public DrawMainResponseDto getDrawMainPageInfo(Integer userId) {
ShareInfo shareInfo = shareInfoRepository.findShareInfoByUserId(userId)
.orElseThrow(() -> new ShareInfoException(ErrorStatus._NOT_FOUND));

int drawParticipationCount = drawParticipationInfo.getDrawParticipationCount();
int drawAttendanceCount = handleAttendanceCount(userId, drawParticipationInfo);
int invitedNum = shareInfo.getInvitedNum();
int remainDrawCount = shareInfo.getRemainDrawCount();

if (drawParticipationCount == 7) {
System.out.println("Draw Attendance = " + drawAttendanceCount);

if (drawAttendanceCount >= 7) {
// 7일 연속 출석자라면
return drawResponseGenerateUtil.generateMainFullAttendResponse(invitedNum, remainDrawCount, drawParticipationCount);
return drawResponseGenerateUtil.generateMainFullAttendResponse(invitedNum, remainDrawCount, drawAttendanceCount % 8);
} else {
// 연속 출석자가 아니라면
return drawResponseGenerateUtil.generateMainNotAttendResponse(invitedNum, remainDrawCount, drawParticipationCount);
return drawResponseGenerateUtil.generateMainNotAttendResponse(invitedNum, remainDrawCount, drawAttendanceCount);
}
}

/**
* 연속 출석인지 판단
* 1. 연속 출석이면 연속 출석일수 1 증가하여 DB에 업데이트
* 2. 연속 출석이 아니면 DB에 연속 출석일수 1로 초기화
* 3. 현재 출석시각을 마지막 출석시각으로 DB에 업데이트
*
* @param userId 사용자 아이디
* @param drawParticipationInfo 참여 정보
* @return 연속출석 일수 반환
*/
private int handleAttendanceCount(Integer userId, DrawParticipationInfo drawParticipationInfo) {
LocalDateTime lastAttendance = drawParticipationInfo.getLastAttendance();

// 한 번도 접속한 적이 없는 사람이라면
if (lastAttendance == null) {
// 연속출석일수 1로 초기화
drawParticipationInfoRepository.setAttendanceCountToOne(userId);

// lastAttendance를 현재 시각으로 설정
drawParticipationInfoRepository.setLastAttendance(userId, LocalDateTime.now());

return 1;
}

// 마지막 접속 시간이 오늘이라면 false 반환
if (isLastAttendanceToday(lastAttendance)) {
// lastAttendance를 현재 시각으로 설정
drawParticipationInfoRepository.setLastAttendance(userId, LocalDateTime.now());

return drawParticipationInfo.getDrawAttendanceCount();
}

if (isContinuousAttendance(lastAttendance)) {
// 연속 출석이라면 연속출석일수 1 증가
drawParticipationInfoRepository.increaseAttendanceCount(userId);

// lastAttendance를 현재 시각으로 설정
drawParticipationInfoRepository.setLastAttendance(userId, LocalDateTime.now());
return drawParticipationInfo.getDrawAttendanceCount() + 1;
} else {
// 연속출석이 아니라면 연속출석일수 1로 초기화
drawParticipationInfoRepository.setAttendanceCountToOne(userId);

// lastAttendance를 현재 시각으로 설정
drawParticipationInfoRepository.setLastAttendance(userId, LocalDateTime.now());
return 1;
}
}

/**
* 연속 출석인지 판단
*
* @param lastAttendance 마지막 출석 날짜
* @return 연속 출석이면 true, 연속출석이 아니면 false 반환
*/
private boolean isContinuousAttendance(LocalDateTime lastAttendance) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime startDateTime = lastAttendance.plusDays(1).with(LocalTime.MIDNIGHT); // 마지막 접속일자의 다음날 자정
LocalDateTime endDateTime = lastAttendance.plusDays(2).with(LocalTime.MIDNIGHT); // 마지막 접속일자의 2일 후 자정

return (now.isAfter(startDateTime) && now.isBefore(endDateTime));
}

/**
* 마지막 출석 시간이 오늘인지 판단
*
* @param lastAttendance 마지막 출석 날짜
* @return 마지막 출석 시간이 오늘이면 true, 아니면 false 반환
*/
private boolean isLastAttendanceToday(LocalDateTime lastAttendance) {
LocalDateTime now = LocalDateTime.now();
LocalDateTime startDateTime = lastAttendance.with(LocalTime.MIDNIGHT);
LocalDateTime endDateTime = lastAttendance.plusDays(1).with(LocalTime.MIDNIGHT);

return (now.isAfter(startDateTime) && now.isBefore(endDateTime));
}

/**
* 추첨 이벤트 당첨 로직 작성
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.softeer.backend.fo_domain.user.repository.UserRepository;
import com.softeer.backend.global.common.code.status.ErrorStatus;
import com.softeer.backend.global.common.constant.RedisKeyPrefix;
import com.softeer.backend.global.util.DrawRedisUtil;
import com.softeer.backend.global.util.EventLockRedisUtil;
import jakarta.annotation.PostConstruct;
import lombok.Getter;
Expand All @@ -31,6 +32,7 @@ public class DrawSettingManager {
private final DrawSettingRepository drawSettingRepository;
private final ThreadPoolTaskScheduler taskScheduler;
private final EventLockRedisUtil eventLockRedisUtil;
private final DrawRedisUtil drawRedisUtil;
private final UserRepository userRepository;

private LocalDate startDate;
Expand Down Expand Up @@ -60,23 +62,29 @@ public void initializeDrawSettingManager() {
// 매일 01:00:00에 redis 당첨자 목록 데이터베이스에 저장
taskScheduler.schedule(this::addWinnerToDatabase, new CronTrigger("0 0 1 * * *"));

// 매일 01:00:00에 redis 임시 당첨자 목록 삭제하기
taskScheduler.schedule(this::deleteTempWinnerSetFromRedis, new CronTrigger("0 0 1 * * *"));
// 매일 01:00:00에 redis 당첨자 목록 삭제하기
taskScheduler.schedule(this::deleteWinnerSetFromRedis, new CronTrigger("0 0 1 * * *"));
}

private void deleteTempWinnerSetFromRedis() {
String drawTempKey;
/**
* 당첨자 목록 모두 삭제
*/
private void deleteWinnerSetFromRedis() {
String drawWinnerKey;
for (int ranking = 1; ranking < 4; ranking++) {
drawTempKey = RedisKeyPrefix.DRAW_WINNER_LIST_PREFIX.getPrefix() + ranking;
eventLockRedisUtil.deleteTempWinnerList(drawTempKey);
drawWinnerKey = RedisKeyPrefix.DRAW_WINNER_LIST_PREFIX.getPrefix() + ranking;
drawRedisUtil.deleteAllSetData(drawWinnerKey);
}
}

/**
* 당첨자 목록 모두 데이터베이스에 저장
*/
private void addWinnerToDatabase() {
String drawWinnerKey;
for (int ranking = 1; ranking < 4; ranking++) {
drawWinnerKey = RedisKeyPrefix.DRAW_WINNER_LIST_PREFIX.getPrefix() + ranking;
Set<Integer> winnerSet = eventLockRedisUtil.getAllDataAsSet(drawWinnerKey);
Set<Integer> winnerSet = drawRedisUtil.getAllDataAsSet(drawWinnerKey);

LocalDateTime winningDate = LocalDateTime.now().minusHours(2); // 하루 전 날 오후 11시로 설정

Expand Down
Loading

0 comments on commit bec7d76

Please sign in to comment.