Skip to content

Commit 8ccfb3c

Browse files
authored
Merge pull request #100 from Daily-Step/feat/99
[Feat] 챌린지 현황 조회 (#99)
2 parents 99c9093 + c784bd2 commit 8ccfb3c

9 files changed

Lines changed: 97 additions & 59 deletions

File tree

src/main/java/com/challenge/api/service/challenge/response/ChallengeResponse.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.challenge.api.service.category.response.CategoryResponse;
44
import com.challenge.api.service.record.response.RecordResponse;
55
import com.challenge.domain.challenge.Challenge;
6+
import com.challenge.domain.challenge.ChallengeStatus;
67
import com.challenge.utils.date.DateUtils;
78
import lombok.Builder;
89
import lombok.Getter;
@@ -15,6 +16,7 @@ public class ChallengeResponse {
1516
private final RecordResponse record;
1617
private final String title;
1718
private final String content;
19+
private final ChallengeStatus status;
1820
private final int durationInWeeks;
1921
private final int weekGoalCount;
2022
private final int totalGoalCount;
@@ -24,13 +26,14 @@ public class ChallengeResponse {
2426

2527
@Builder
2628
private ChallengeResponse(Long id, CategoryResponse category, RecordResponse record, String title,
27-
String content, int durationInWeeks, int weekGoalCount, int totalGoalCount, String color,
28-
String startDateTime, String endDateTime) {
29+
String content, ChallengeStatus status, int durationInWeeks, int weekGoalCount,
30+
int totalGoalCount, String color, String startDateTime, String endDateTime) {
2931
this.id = id;
3032
this.category = category;
3133
this.record = record;
3234
this.title = title;
3335
this.content = content;
36+
this.status = status;
3437
this.durationInWeeks = durationInWeeks;
3538
this.weekGoalCount = weekGoalCount;
3639
this.totalGoalCount = totalGoalCount;
@@ -46,6 +49,7 @@ public static ChallengeResponse of(Challenge challenge) {
4649
.record(RecordResponse.of(challenge))
4750
.title(challenge.getTitle())
4851
.content(challenge.getContent())
52+
.status(challenge.getStatus())
4953
.durationInWeeks(challenge.getDurationInWeeks())
5054
.weekGoalCount(challenge.getWeeklyGoalCount())
5155
.totalGoalCount(challenge.getTotalGoalCount())

src/main/java/com/challenge/domain/challenge/Challenge.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import jakarta.persistence.CascadeType;
1010
import jakarta.persistence.Column;
1111
import jakarta.persistence.Entity;
12+
import jakarta.persistence.EnumType;
13+
import jakarta.persistence.Enumerated;
1214
import jakarta.persistence.FetchType;
1315
import jakarta.persistence.GeneratedValue;
1416
import jakarta.persistence.GenerationType;
@@ -52,6 +54,10 @@ public class Challenge extends BaseDateTimeEntity {
5254
@Column(length = 500)
5355
private String content;
5456

57+
@Enumerated(EnumType.STRING)
58+
@Column(columnDefinition = "VARCHAR(10)", nullable = false)
59+
private ChallengeStatus status;
60+
5561
@Column(nullable = false)
5662
private int durationInWeeks;
5763

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

67-
@Column(nullable = false)
68-
private boolean isDeleted = false;
69-
7073
@Column(nullable = false)
7174
private LocalDateTime startDateTime;
7275

7376
@Column(nullable = false)
7477
private LocalDateTime endDateTime;
7578

7679
@Builder
77-
private Challenge(Member member, Category category, String title, String content, int durationInWeeks,
78-
int weeklyGoalCount, String color, boolean isDeleted, LocalDateTime startDateTime) {
80+
private Challenge(Member member, Category category, String title, String content, ChallengeStatus status,
81+
int durationInWeeks, int weeklyGoalCount, String color, LocalDateTime startDateTime) {
7982
this.challengeRecords = new ArrayList<>();
8083
this.member = member;
8184
this.category = category;
8285
this.title = title;
8386
this.content = content;
87+
this.status = status;
8488
this.durationInWeeks = durationInWeeks;
8589
this.weeklyGoalCount = weeklyGoalCount;
8690
this.totalGoalCount = durationInWeeks * weeklyGoalCount;
8791
this.color = color;
88-
this.isDeleted = isDeleted;
8992
this.startDateTime = startDateTime;
9093
this.endDateTime = startDateTime.plusWeeks(durationInWeeks)
9194
.toLocalDate()
@@ -95,12 +98,13 @@ private Challenge(Member member, Category category, String title, String content
9598
}
9699

97100
public static Challenge create(Member member, Category category, ChallengeCreateServiceRequest request,
98-
LocalDateTime startDateTime) {
101+
LocalDateTime startDateTime) {
99102
return Challenge.builder()
100103
.member(member)
101104
.category(category)
102105
.title(request.getTitle())
103106
.content(request.getContent())
107+
.status(ChallengeStatus.ONGOING)
104108
.durationInWeeks(request.getDurationInWeeks())
105109
.weeklyGoalCount(request.getWeeklyGoalCount())
106110
.color(request.getColor())
@@ -120,7 +124,7 @@ public void addRecord(ChallengeRecord challengeRecord) {
120124
}
121125

122126
public void delete() {
123-
this.isDeleted = true;
127+
this.status = ChallengeStatus.REMOVED;
124128
}
125129

126130
}

src/main/java/com/challenge/domain/challenge/ChallengeQueryRepository.java

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.challenge.domain.challenge;
22

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

2726
return queryFactory.selectFrom(challenge)
2827
.where(challenge.member.eq(member)
29-
.and(challenge.isDeleted.isFalse())
28+
.and(challenge.status.ne(ChallengeStatus.REMOVED))
3029
.and(challenge.endDateTime.goe(startDateTime))
3130
.and(challenge.startDateTime.loe(endDateTime)))
3231
.fetch();
@@ -44,41 +43,31 @@ public boolean existsDuplicateRecordBy(Challenge challenge, LocalDate successDat
4443
return count != null && count > 0;
4544
}
4645

47-
// 진행중인 챌린지 수 조회 테스트용
48-
public Long countOngoingChallengesBy(Member member, String targetDateTime) {
49-
LocalDateTime now = DateUtils.toLocalDateTime(targetDateTime);
46+
// 진행중인 챌린지 수 조회
47+
public Long countOngoingChallengesBy(Member member) {
5048
return queryFactory.select(challenge.count())
5149
.from(challenge)
5250
.where(challenge.member.eq(member)
53-
.and(challenge.isDeleted.isFalse())
54-
.and(challenge.endDateTime.goe(now))
51+
.and(challenge.status.eq(ChallengeStatus.ONGOING))
5552
)
5653
.fetchOne();
5754
}
5855

59-
// 진행중인 챌린지 수 조회
60-
public Long countOngoingChallengesBy(Member member) {
61-
LocalDateTime now = LocalDateTime.now();
56+
// 완료된 챌린지 수 조회
57+
public Long countSucceedChallengesBy(Member member) {
6258
return queryFactory.select(challenge.count())
6359
.from(challenge)
6460
.where(challenge.member.eq(member)
65-
.and(challenge.isDeleted.isFalse())
66-
.and(challenge.endDateTime.goe(now))
67-
)
61+
.and(challenge.status.eq(ChallengeStatus.SUCCEED)))
6862
.fetchOne();
6963
}
7064

71-
// 완료된 챌린지 수 조회
72-
public Long countCompletedChallengesBy(Member member) {
73-
return null;
74-
}
75-
7665
// 전체 챌린지 수 조회
7766
public Long countAllChallengesBy(Member member) {
7867
return queryFactory.select(challenge.count())
7968
.from(challenge)
8069
.where(challenge.member.eq(member)
81-
.and(challenge.isDeleted.isFalse()))
70+
.and(challenge.status.ne(ChallengeStatus.REMOVED)))
8271
.fetchOne();
8372
}
8473

src/main/java/com/challenge/domain/challenge/ChallengeStatus.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@
77
@Getter
88
public enum ChallengeStatus {
99

10-
// - Q. 챌린지 기간이 만료되는 경우, 어떻게 자동으로 챌린지의 상태를 변경할 수 있을까?
11-
// A. 스케줄러 라이브러리를 사용하여 매 00시 00분 00초에 챌린지의 상태를 확인하여 챌린지 기간이 만료된 경우 상태를 변경한다.
12-
13-
// - Q. 챌린지의 상태를 변경하는 로직은 어디에 위치하는 것이 좋을까?
14-
// A. 챌린지의 상태를 변경하는 로직은 챌린지 도메인에 위치하는 것이 좋다.
15-
1610
ONGOING("진행 중"),
17-
SUCCEED("성공"), // 모든 목표를 달성한 경우
18-
FAILED("실패"), // 하나라도 목표를 달성하지 못한 경우
11+
SUCCEED("성공"),
12+
EXPIRED("기간 만료"),
1913
REMOVED("삭제");
2014

2115
private final String description;

src/test/java/com/challenge/api/service/challenge/ChallengeServiceTest.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.challenge.domain.category.CategoryRepository;
1212
import com.challenge.domain.challenge.Challenge;
1313
import com.challenge.domain.challenge.ChallengeRepository;
14+
import com.challenge.domain.challenge.ChallengeStatus;
1415
import com.challenge.domain.challengeRecord.ChallengeRecord;
1516
import com.challenge.domain.challengeRecord.ChallengeRecordRepository;
1617
import com.challenge.domain.job.Job;
@@ -368,10 +369,10 @@ void deleteChallenge() {
368369
// then - 삭제된 챌린지 검증
369370
assertThat(deletedChallenge).isEqualTo(challenge2.getId());
370371
assertThat(challengeRepository.findAll()).hasSize(2)
371-
.extracting("title", "content", "isDeleted")
372+
.extracting("title", "content", "status")
372373
.containsExactly(
373-
tuple("제목1", "내용1", false),
374-
tuple("제목2", "내용2", true)
374+
tuple("제목1", "내용1", ChallengeStatus.ONGOING),
375+
tuple("제목2", "내용2", ChallengeStatus.REMOVED)
375376
);
376377

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

415416
private Challenge createChallenge(Member member, Category category, int durationInWeeks, String title,
416-
LocalDateTime startDateTime) {
417+
LocalDateTime startDateTime) {
417418
return Challenge.builder()
418419
.member(member)
419420
.category(category)
420421
.durationInWeeks(durationInWeeks)
421422
.title(title)
423+
.status(ChallengeStatus.ONGOING)
422424
.color("#30B0C7")
423425
.weeklyGoalCount(1)
424426
.startDateTime(startDateTime)

src/test/java/com/challenge/api/validator/RecordValidatorTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.challenge.domain.category.CategoryRepository;
55
import com.challenge.domain.challenge.Challenge;
66
import com.challenge.domain.challenge.ChallengeRepository;
7+
import com.challenge.domain.challenge.ChallengeStatus;
78
import com.challenge.domain.challengeRecord.ChallengeRecord;
89
import com.challenge.domain.challengeRecord.ChallengeRecordRepository;
910
import com.challenge.domain.job.Job;
@@ -125,6 +126,7 @@ private Challenge createChallenge(Member member, Category category, LocalDateTim
125126
.member(member)
126127
.category(category)
127128
.title("제목")
129+
.status(ChallengeStatus.ONGOING)
128130
.color("#30B0C7")
129131
.durationInWeeks(1)
130132
.weeklyGoalCount(1)

src/test/java/com/challenge/docs/ChallengeControllerDocsTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.challenge.api.service.challenge.request.ChallengeUpdateServiceRequest;
1212
import com.challenge.api.service.challenge.response.ChallengeResponse;
1313
import com.challenge.api.service.record.response.RecordResponse;
14+
import com.challenge.domain.challenge.ChallengeStatus;
1415
import com.challenge.domain.member.Member;
1516
import com.challenge.utils.date.DateUtils;
1617
import org.junit.jupiter.api.DisplayName;
@@ -82,6 +83,7 @@ void getChallenges() throws Exception {
8283
.build())
8384
.title("챌린지 제목1")
8485
.content("챌린지 내용1")
86+
.status(ChallengeStatus.ONGOING)
8587
.durationInWeeks(1)
8688
.weekGoalCount(2)
8789
.totalGoalCount(4)
@@ -104,6 +106,7 @@ void getChallenges() throws Exception {
104106
.build())
105107
.title("챌린지 제목2")
106108
.content("챌린지 내용2")
109+
.status(ChallengeStatus.ONGOING)
107110
.durationInWeeks(2)
108111
.weekGoalCount(2)
109112
.totalGoalCount(4)
@@ -148,6 +151,8 @@ void getChallenges() throws Exception {
148151
fieldWithPath("data[].content").type(STRING)
149152
.optional()
150153
.description("챌린지 내용"),
154+
fieldWithPath("data[].status").type(STRING)
155+
.description("챌린지 상태"),
151156
fieldWithPath("data[].durationInWeeks").type(NUMBER)
152157
.description("챌린지 기간 (주 단위)"),
153158
fieldWithPath("data[].weekGoalCount").type(NUMBER)
@@ -196,6 +201,7 @@ void createChallengeSuccess() throws Exception {
196201
.record(null)
197202
.title("챌린지 제목")
198203
.content("챌린지 내용")
204+
.status(ChallengeStatus.ONGOING)
199205
.durationInWeeks(2)
200206
.weekGoalCount(2)
201207
.totalGoalCount(4)
@@ -247,6 +253,8 @@ void createChallengeSuccess() throws Exception {
247253
fieldWithPath("data.content").type(STRING)
248254
.optional()
249255
.description("챌린지 내용"),
256+
fieldWithPath("data.status").type(STRING)
257+
.description("챌린지 상태"),
250258
fieldWithPath("data.durationInWeeks").type(NUMBER)
251259
.description("챌린지 기간 (주 단위)"),
252260
fieldWithPath("data.weekGoalCount").type(NUMBER)
@@ -330,6 +338,7 @@ void achieveChallenge() throws Exception {
330338
.build())
331339
.title("챌린지 제목")
332340
.content("챌린지 내용")
341+
.status(ChallengeStatus.ONGOING)
333342
.durationInWeeks(2)
334343
.weekGoalCount(2)
335344
.totalGoalCount(4)
@@ -377,6 +386,9 @@ void achieveChallenge() throws Exception {
377386
fieldWithPath("data.content").type(STRING)
378387
.optional()
379388
.description("챌린지 내용"),
389+
fieldWithPath("data.status").type(STRING)
390+
.optional()
391+
.description("챌린지 상태"),
380392
fieldWithPath("data.durationInWeeks").type(NUMBER)
381393
.description("챌린지 기간 (주 단위)"),
382394
fieldWithPath("data.weekGoalCount").type(NUMBER)
@@ -425,6 +437,7 @@ void cancelChallenge() throws Exception {
425437
.build())
426438
.title("챌린지 제목")
427439
.content("챌린지 내용")
440+
.status(ChallengeStatus.ONGOING)
428441
.durationInWeeks(2)
429442
.weekGoalCount(2)
430443
.totalGoalCount(4)
@@ -474,6 +487,8 @@ void cancelChallenge() throws Exception {
474487
fieldWithPath("data.content").type(STRING)
475488
.optional()
476489
.description("챌린지 내용"),
490+
fieldWithPath("data.status").type(STRING)
491+
.description("챌린지 상태"),
477492
fieldWithPath("data.durationInWeeks").type(NUMBER)
478493
.description("챌린지 기간 (주 단위)"),
479494
fieldWithPath("data.weekGoalCount").type(NUMBER)
@@ -523,6 +538,7 @@ void updateChallenge() throws Exception {
523538
.build())
524539
.title("수정된 챌린지 제목")
525540
.content("수정된 챌린지 내용")
541+
.status(ChallengeStatus.ONGOING)
526542
.durationInWeeks(2)
527543
.weekGoalCount(2)
528544
.totalGoalCount(4)
@@ -576,6 +592,8 @@ void updateChallenge() throws Exception {
576592
fieldWithPath("data.content").type(STRING)
577593
.optional()
578594
.description("챌린지 내용"),
595+
fieldWithPath("data.status").type(STRING)
596+
.description("챌린지 상태"),
579597
fieldWithPath("data.durationInWeeks").type(NUMBER)
580598
.description("챌린지 기간 (주 단위)"),
581599
fieldWithPath("data.weekGoalCount").type(NUMBER)

0 commit comments

Comments
 (0)