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 @@ -99,10 +99,13 @@ public ChallengeResponse cancelChallenge(Member member, Long challengeId, Challe
Challenge challenge = challengeRepository.getReferenceById(challengeId);

// validation
Record record = recordValidator.hasRecordFor(challenge, DateUtils.toLocalDate(request.getCancelDate()));
// TODO 마지막 record 상태를 가져와 is_succeed 상태가 true인지 확인
recordValidator.hasRecordFor(challenge, DateUtils.toLocalDate(request.getCancelDate()));

// 기록 삭제
challenge.getRecords().remove(record);
Record record = Record.cancel(challenge, request.getCancelDate());
recordRepository.save(record);

return ChallengeResponse.of(challenge);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static RecordResponse of(Challenge challenge) {
return RecordResponse.builder()
.successDates(
records.stream()
.map(record -> DateUtils.toDayString(record.getSuccessDate()))
.map(record -> DateUtils.toDayString(record.getDate()))
.toList()
)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class RecordValidator {
*/
public Record hasRecordFor(Challenge challenge, LocalDate cancelDate) {
return challenge.getRecords().stream()
.filter(r -> r.getSuccessDate().equals(cancelDate))
.filter(r -> r.getDate().equals(cancelDate))
.findFirst()
.orElseThrow(() -> new GlobalException(ErrorCode.RECORD_NOT_FOUND));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.challenge.domain.challenge;

import com.challenge.domain.member.Member;
import com.challenge.utils.date.DateUtils;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -18,9 +20,7 @@ public class ChallengeQueryRepository {

private final JPAQueryFactory queryFactory;

/**
* 입력 받은 날짜 기준 이전 2달간의 챌린지 목록 조회 (2달전 00:00:00 ~ 입력받은 날짜 23:59:59)
*/
// 입력 받은 날짜 기준 이전 2달간의 챌린지 목록 조회 (2달전 00:00:00 ~ 입력받은 날짜 23:59:59)
public List<Challenge> findChallengesBy(Member member, LocalDate targetDate) {
LocalDateTime startDateTime = targetDate.minusMonths(2).atStartOfDay();
LocalDateTime endDateTime = targetDate.atTime(23, 59, 59);
Expand All @@ -33,6 +33,7 @@ public List<Challenge> findChallengesBy(Member member, LocalDate targetDate) {
.fetch();
}

// 중복된 기록이 존재하는지 조회
public boolean existsDuplicateRecordBy(Challenge challenge, LocalDate successDate) {
Long count = queryFactory.select(record.count())
.from(record)
Expand All @@ -43,4 +44,52 @@ public boolean existsDuplicateRecordBy(Challenge challenge, LocalDate successDat
return count != null && count > 0;
}

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

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

// 완료된 챌린지 수 조회
public Long countCompletedChallengesBy(Member member) {
return queryFactory
.select(challenge.count())
.from(challenge)
.leftJoin(record)
.on(record.challenge.eq(challenge)
.and(record.isSucceed.isTrue())
)
.where(challenge.member.eq(member))
.groupBy(challenge)
.having(record.count().eq(Expressions.constant(challenge.totalGoalCount)))
.fetchOne();
}

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

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

public interface ChallengeRepository extends JpaRepository<Challenge, Long> {

// 해당 멤버에 대한 챌린지 존재 여부 조회
boolean existsByMemberAndId(Member member, Long challengeId);

}
33 changes: 22 additions & 11 deletions src/main/java/com/challenge/domain/record/Record.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -23,9 +21,6 @@
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
uniqueConstraints = @UniqueConstraint(columnNames = {"challenge_id", "success_date"})
)
public class Record extends BaseDateTimeEntity {

@Id
Expand All @@ -34,24 +29,40 @@ public class Record extends BaseDateTimeEntity {
private Long id;

@Column(nullable = false)
private LocalDate successDate;
private LocalDate date;

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "challenge_id", nullable = false)
private Challenge challenge;

@Builder
private Record(LocalDate successDate, Challenge challenge) {
this.successDate = successDate;
private Record(LocalDate date, boolean isSucceed, Challenge challenge) {
this.date = date;
this.challenge = challenge;
challenge.addRecord(this);
this.isSucceed = isSucceed;
}

public static Record achieve(Challenge challenge, String achieveDate) {
return Record.builder()
Record record = Record.builder()
.date(DateUtils.toLocalDate(achieveDate))
.isSucceed(true)
.challenge(challenge)
.build();
challenge.addRecord(record);
return record;
}

public static Record cancel(Challenge challenge, String cancelDate) {
Record record = Record.builder()
.date(DateUtils.toLocalDate(cancelDate))
.isSucceed(false)
.challenge(challenge)
.successDate(DateUtils.toLocalDate(achieveDate))
.build();
challenge.getRecords().remove(record);
return record;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private Category createCategory() {
private Record createRecord(Challenge challenge, LocalDate currentDate) {
return Record.builder()
.challenge(challenge)
.successDate(currentDate)
.date(currentDate)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,64 @@ void existsDuplicateRecordBy() {
assertThat(result).isTrue();
}

@DisplayName("진행중인 챌린지 수를 조회한다.")
@Test
void countOngoingChallengesBy() {
// given
String targetDateTime = "2025-01-08 12:30:59";

Member member = createMember();
memberRepository.save(member);

Category category = createCategory();
categoryRepository.save(category);

Challenge challenge1 = createChallenge(member, category, 1, "제목1",
LocalDateTime.of(2024, 10, 1, 12, 30, 59));
Challenge challenge2 = createChallenge(member, category, 2, "제목2",
LocalDateTime.of(2024, 11, 11, 14, 0, 0));
Challenge challenge3 = createChallenge(member, category, 3, "제목3",
LocalDateTime.of(2024, 12, 23, 0, 0, 0));
Challenge challenge4 = createChallenge(member, category, 1, "제목4",
LocalDateTime.of(2025, 1, 1, 0, 0, 0));
challengeRepository.saveAll(List.of(challenge1, challenge2, challenge3, challenge4));

// when
Long count = challengeQueryRepository.countOngoingChallengesBy(member, targetDateTime);

// then
assertThat(count).isEqualTo(2);
}

@DisplayName("완료된 챌린지 수를 조회한다.")
@Test
void countCompletedChallengesBy() {
// given
Member member = createMember();
memberRepository.save(member);

Category category = createCategory();
categoryRepository.save(category);

Challenge challenge1 = createChallenge(member, category, 1, "제목1",
LocalDateTime.of(2025, 1, 1, 12, 30, 59));

Record record1 = createRecord(challenge1, LocalDate.of(2025, 1, 1));
Record record2 = createRecord(challenge1, LocalDate.of(2025, 1, 2));
Record record3 = createRecord(challenge1, LocalDate.of(2025, 1, 3));
Record record4 = createRecord(challenge1, LocalDate.of(2025, 1, 4));
Record record5 = createRecord(challenge1, LocalDate.of(2025, 1, 5));
Record record6 = createRecord(challenge1, LocalDate.of(2025, 1, 6));
Record record7 = createRecord(challenge1, LocalDate.of(2025, 1, 7));
recordRepository.saveAll(List.of(record1, record2, record3, record4, record5, record6, record7));

// when
Long count = challengeQueryRepository.countCompletedChallengesBy(member);

// then
assertThat(count).isEqualTo(1);
}

private Member createMember() {
Job job = Job.builder()
.code("1")
Expand Down
Loading