Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.challenge.api.service.category.response.CategoryResponse;
import com.challenge.api.service.record.response.RecordResponse;
import com.challenge.domain.challenge.Challenge;
import com.challenge.domain.challenge.ChallengeStatus;
import com.challenge.utils.date.DateUtils;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -15,6 +16,7 @@ public class ChallengeResponse {
private final RecordResponse record;
private final String title;
private final String content;
private final ChallengeStatus status;
private final int durationInWeeks;
private final int weekGoalCount;
private final int totalGoalCount;
Expand All @@ -24,13 +26,14 @@ public class ChallengeResponse {

@Builder
private ChallengeResponse(Long id, CategoryResponse category, RecordResponse record, String title,
String content, int durationInWeeks, int weekGoalCount, int totalGoalCount, String color,
String startDateTime, String endDateTime) {
String content, ChallengeStatus status, int durationInWeeks, int weekGoalCount,
int totalGoalCount, String color, String startDateTime, String endDateTime) {
this.id = id;
this.category = category;
this.record = record;
this.title = title;
this.content = content;
this.status = status;
this.durationInWeeks = durationInWeeks;
this.weekGoalCount = weekGoalCount;
this.totalGoalCount = totalGoalCount;
Expand All @@ -46,6 +49,7 @@ public static ChallengeResponse of(Challenge challenge) {
.record(RecordResponse.of(challenge))
.title(challenge.getTitle())
.content(challenge.getContent())
.status(challenge.getStatus())
.durationInWeeks(challenge.getDurationInWeeks())
.weekGoalCount(challenge.getWeeklyGoalCount())
.totalGoalCount(challenge.getTotalGoalCount())
Expand Down
20 changes: 12 additions & 8 deletions src/main/java/com/challenge/domain/challenge/Challenge.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
Expand Down Expand Up @@ -52,6 +54,10 @@ public class Challenge extends BaseDateTimeEntity {
@Column(length = 500)
private String content;

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "VARCHAR(10)", nullable = false)
private ChallengeStatus status;

@Column(nullable = false)
private int durationInWeeks;

Expand All @@ -64,28 +70,25 @@ public class Challenge extends BaseDateTimeEntity {
@Column(nullable = false, length = 10)
private String color;

@Column(nullable = false)
private boolean isDeleted = false;

@Column(nullable = false)
private LocalDateTime startDateTime;

@Column(nullable = false)
private LocalDateTime endDateTime;

@Builder
private Challenge(Member member, Category category, String title, String content, int durationInWeeks,
int weeklyGoalCount, String color, boolean isDeleted, LocalDateTime startDateTime) {
private Challenge(Member member, Category category, String title, String content, ChallengeStatus status,
int durationInWeeks, int weeklyGoalCount, String color, LocalDateTime startDateTime) {
this.challengeRecords = new ArrayList<>();
this.member = member;
this.category = category;
this.title = title;
this.content = content;
this.status = status;
this.durationInWeeks = durationInWeeks;
this.weeklyGoalCount = weeklyGoalCount;
this.totalGoalCount = durationInWeeks * weeklyGoalCount;
this.color = color;
this.isDeleted = isDeleted;
this.startDateTime = startDateTime;
this.endDateTime = startDateTime.plusWeeks(durationInWeeks)
.toLocalDate()
Expand All @@ -95,12 +98,13 @@ private Challenge(Member member, Category category, String title, String content
}

public static Challenge create(Member member, Category category, ChallengeCreateServiceRequest request,
LocalDateTime startDateTime) {
LocalDateTime startDateTime) {
return Challenge.builder()
.member(member)
.category(category)
.title(request.getTitle())
.content(request.getContent())
.status(ChallengeStatus.ONGOING)
.durationInWeeks(request.getDurationInWeeks())
.weeklyGoalCount(request.getWeeklyGoalCount())
.color(request.getColor())
Expand All @@ -120,7 +124,7 @@ public void addRecord(ChallengeRecord challengeRecord) {
}

public void delete() {
this.isDeleted = true;
this.status = ChallengeStatus.REMOVED;
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.challenge.domain.challenge;

import com.challenge.domain.member.Member;
import com.challenge.utils.date.DateUtils;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -26,7 +25,7 @@ public List<Challenge> findChallengesBy(Member member, LocalDate targetDate) {

return queryFactory.selectFrom(challenge)
.where(challenge.member.eq(member)
.and(challenge.isDeleted.isFalse())
.and(challenge.status.ne(ChallengeStatus.REMOVED))
.and(challenge.endDateTime.goe(startDateTime))
.and(challenge.startDateTime.loe(endDateTime)))
.fetch();
Expand All @@ -44,41 +43,31 @@ public boolean existsDuplicateRecordBy(Challenge challenge, LocalDate successDat
return count != null && count > 0;
}

// 진행중인 챌린지 수 조회 테스트용
public Long countOngoingChallengesBy(Member member, String targetDateTime) {
LocalDateTime now = DateUtils.toLocalDateTime(targetDateTime);
// 진행중인 챌린지 수 조회
public Long countOngoingChallengesBy(Member member) {
return queryFactory.select(challenge.count())
.from(challenge)
.where(challenge.member.eq(member)
.and(challenge.isDeleted.isFalse())
.and(challenge.endDateTime.goe(now))
.and(challenge.status.eq(ChallengeStatus.ONGOING))
)
.fetchOne();
}

// 진행중인 챌린지 수 조회
public Long countOngoingChallengesBy(Member member) {
LocalDateTime now = LocalDateTime.now();
// 완료된 챌린지 수 조회
public Long countSucceedChallengesBy(Member member) {
return queryFactory.select(challenge.count())
.from(challenge)
.where(challenge.member.eq(member)
.and(challenge.isDeleted.isFalse())
.and(challenge.endDateTime.goe(now))
)
.and(challenge.status.eq(ChallengeStatus.SUCCEED)))
.fetchOne();
}

// 완료된 챌린지 수 조회
public Long countCompletedChallengesBy(Member member) {
return null;
}

// 전체 챌린지 수 조회
public Long countAllChallengesBy(Member member) {
return queryFactory.select(challenge.count())
.from(challenge)
.where(challenge.member.eq(member)
.and(challenge.isDeleted.isFalse()))
.and(challenge.status.ne(ChallengeStatus.REMOVED)))
.fetchOne();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@
@Getter
public enum ChallengeStatus {

// - Q. 챌린지 기간이 만료되는 경우, 어떻게 자동으로 챌린지의 상태를 변경할 수 있을까?
// A. 스케줄러 라이브러리를 사용하여 매 00시 00분 00초에 챌린지의 상태를 확인하여 챌린지 기간이 만료된 경우 상태를 변경한다.

// - Q. 챌린지의 상태를 변경하는 로직은 어디에 위치하는 것이 좋을까?
// A. 챌린지의 상태를 변경하는 로직은 챌린지 도메인에 위치하는 것이 좋다.

ONGOING("진행 중"),
SUCCEED("성공"), // 모든 목표를 달성한 경우
FAILED("실패"), // 하나라도 목표를 달성하지 못한 경우
SUCCEED("성공"),
EXPIRED("기간 만료"),
REMOVED("삭제");

private final String description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.challenge.domain.category.CategoryRepository;
import com.challenge.domain.challenge.Challenge;
import com.challenge.domain.challenge.ChallengeRepository;
import com.challenge.domain.challenge.ChallengeStatus;
import com.challenge.domain.challengeRecord.ChallengeRecord;
import com.challenge.domain.challengeRecord.ChallengeRecordRepository;
import com.challenge.domain.job.Job;
Expand Down Expand Up @@ -368,10 +369,10 @@ void deleteChallenge() {
// then - 삭제된 챌린지 검증
assertThat(deletedChallenge).isEqualTo(challenge2.getId());
assertThat(challengeRepository.findAll()).hasSize(2)
.extracting("title", "content", "isDeleted")
.extracting("title", "content", "status")
.containsExactly(
tuple("제목1", "내용1", false),
tuple("제목2", "내용2", true)
tuple("제목1", "내용1", ChallengeStatus.ONGOING),
tuple("제목2", "내용2", ChallengeStatus.REMOVED)
);

// given - 모든 챌린지 조회를 위한 요청 request
Expand Down Expand Up @@ -413,12 +414,13 @@ private Member createMember() {
}

private Challenge createChallenge(Member member, Category category, int durationInWeeks, String title,
LocalDateTime startDateTime) {
LocalDateTime startDateTime) {
return Challenge.builder()
.member(member)
.category(category)
.durationInWeeks(durationInWeeks)
.title(title)
.status(ChallengeStatus.ONGOING)
.color("#30B0C7")
.weeklyGoalCount(1)
.startDateTime(startDateTime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.challenge.domain.category.CategoryRepository;
import com.challenge.domain.challenge.Challenge;
import com.challenge.domain.challenge.ChallengeRepository;
import com.challenge.domain.challenge.ChallengeStatus;
import com.challenge.domain.challengeRecord.ChallengeRecord;
import com.challenge.domain.challengeRecord.ChallengeRecordRepository;
import com.challenge.domain.job.Job;
Expand Down Expand Up @@ -125,6 +126,7 @@ private Challenge createChallenge(Member member, Category category, LocalDateTim
.member(member)
.category(category)
.title("제목")
.status(ChallengeStatus.ONGOING)
.color("#30B0C7")
.durationInWeeks(1)
.weeklyGoalCount(1)
Expand Down
18 changes: 18 additions & 0 deletions src/test/java/com/challenge/docs/ChallengeControllerDocsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.challenge.api.service.challenge.request.ChallengeUpdateServiceRequest;
import com.challenge.api.service.challenge.response.ChallengeResponse;
import com.challenge.api.service.record.response.RecordResponse;
import com.challenge.domain.challenge.ChallengeStatus;
import com.challenge.domain.member.Member;
import com.challenge.utils.date.DateUtils;
import org.junit.jupiter.api.DisplayName;
Expand Down Expand Up @@ -82,6 +83,7 @@ void getChallenges() throws Exception {
.build())
.title("챌린지 제목1")
.content("챌린지 내용1")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(1)
.weekGoalCount(2)
.totalGoalCount(4)
Expand All @@ -104,6 +106,7 @@ void getChallenges() throws Exception {
.build())
.title("챌린지 제목2")
.content("챌린지 내용2")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(2)
.weekGoalCount(2)
.totalGoalCount(4)
Expand Down Expand Up @@ -148,6 +151,8 @@ void getChallenges() throws Exception {
fieldWithPath("data[].content").type(STRING)
.optional()
.description("챌린지 내용"),
fieldWithPath("data[].status").type(STRING)
.description("챌린지 상태"),
fieldWithPath("data[].durationInWeeks").type(NUMBER)
.description("챌린지 기간 (주 단위)"),
fieldWithPath("data[].weekGoalCount").type(NUMBER)
Expand Down Expand Up @@ -196,6 +201,7 @@ void createChallengeSuccess() throws Exception {
.record(null)
.title("챌린지 제목")
.content("챌린지 내용")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(2)
.weekGoalCount(2)
.totalGoalCount(4)
Expand Down Expand Up @@ -247,6 +253,8 @@ void createChallengeSuccess() throws Exception {
fieldWithPath("data.content").type(STRING)
.optional()
.description("챌린지 내용"),
fieldWithPath("data.status").type(STRING)
.description("챌린지 상태"),
fieldWithPath("data.durationInWeeks").type(NUMBER)
.description("챌린지 기간 (주 단위)"),
fieldWithPath("data.weekGoalCount").type(NUMBER)
Expand Down Expand Up @@ -330,6 +338,7 @@ void achieveChallenge() throws Exception {
.build())
.title("챌린지 제목")
.content("챌린지 내용")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(2)
.weekGoalCount(2)
.totalGoalCount(4)
Expand Down Expand Up @@ -377,6 +386,9 @@ void achieveChallenge() throws Exception {
fieldWithPath("data.content").type(STRING)
.optional()
.description("챌린지 내용"),
fieldWithPath("data.status").type(STRING)
.optional()
.description("챌린지 상태"),
fieldWithPath("data.durationInWeeks").type(NUMBER)
.description("챌린지 기간 (주 단위)"),
fieldWithPath("data.weekGoalCount").type(NUMBER)
Expand Down Expand Up @@ -425,6 +437,7 @@ void cancelChallenge() throws Exception {
.build())
.title("챌린지 제목")
.content("챌린지 내용")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(2)
.weekGoalCount(2)
.totalGoalCount(4)
Expand Down Expand Up @@ -474,6 +487,8 @@ void cancelChallenge() throws Exception {
fieldWithPath("data.content").type(STRING)
.optional()
.description("챌린지 내용"),
fieldWithPath("data.status").type(STRING)
.description("챌린지 상태"),
fieldWithPath("data.durationInWeeks").type(NUMBER)
.description("챌린지 기간 (주 단위)"),
fieldWithPath("data.weekGoalCount").type(NUMBER)
Expand Down Expand Up @@ -523,6 +538,7 @@ void updateChallenge() throws Exception {
.build())
.title("수정된 챌린지 제목")
.content("수정된 챌린지 내용")
.status(ChallengeStatus.ONGOING)
.durationInWeeks(2)
.weekGoalCount(2)
.totalGoalCount(4)
Expand Down Expand Up @@ -576,6 +592,8 @@ void updateChallenge() throws Exception {
fieldWithPath("data.content").type(STRING)
.optional()
.description("챌린지 내용"),
fieldWithPath("data.status").type(STRING)
.description("챌린지 상태"),
fieldWithPath("data.durationInWeeks").type(NUMBER)
.description("챌린지 기간 (주 단위)"),
fieldWithPath("data.weekGoalCount").type(NUMBER)
Expand Down
Loading
Loading