Skip to content

Commit

Permalink
feat: 미션 전체 현황 - 날짜로 미션 목록 조회 (#315)
Browse files Browse the repository at this point in the history
* feat: 미션 전체 현황 - 날짜로 미션 목록 조회

* fix: Transactional readOnly 추가

* fix: isCompletedMissionToday에 COMPLETE 비교 추가

* fix: 로직 stream으로 변경

* fix: findMissionsWithRecordsByDate 날짜 비교 00으로 변경

* style: spotless

* fix: sorted stream과 합치고 missionSummaryItem메소드 추출
  • Loading branch information
kdomo authored Feb 12, 2024
1 parent e8f0a82 commit c4bad25
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,17 @@
import com.depromeet.domain.mission.application.MissionService;
import com.depromeet.domain.mission.dto.request.MissionCreateRequest;
import com.depromeet.domain.mission.dto.request.MissionUpdateRequest;
import com.depromeet.domain.mission.dto.response.FinishedMissionResponse;
import com.depromeet.domain.mission.dto.response.FollowMissionFindAllResponse;
import com.depromeet.domain.mission.dto.response.MissionCreateResponse;
import com.depromeet.domain.mission.dto.response.MissionFindAllResponse;
import com.depromeet.domain.mission.dto.response.MissionFindResponse;
import com.depromeet.domain.mission.dto.response.MissionSymbolStackResponse;
import com.depromeet.domain.mission.dto.response.MissionUpdateResponse;
import com.depromeet.domain.mission.dto.response.*;
import com.depromeet.domain.missionRecord.dto.response.MissionRecordSummaryResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@Tag(name = "2. [미션]", description = "미션 관련 API입니다.")
@RestController
Expand Down Expand Up @@ -67,6 +55,12 @@ public MissionRecordSummaryResponse missionRecordFindSummary() {
return missionService.findSummaryMissionRecord();
}

@Operation(summary = "미션 전체 현황 - 리스트", description = "년, 월, 일을 입력받아 해당 날짜의 미션 리스트를 조회합니다.")
@GetMapping("/summary-list")
public MissionSummaryListResponse missionSummaryList(@RequestParam LocalDate date) {
return missionService.findSummaryList(date);
}

@Operation(summary = "종료미션 보관함", description = "종료된 미션 리스트를 조회합니다.")
@GetMapping("/finished")
public List<FinishedMissionResponse> missionFindAllFinished() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -303,4 +304,52 @@ public List<MissionRecord> findCompletedMissionRecords(List<Mission> missions) {
missionRecord.getUploadStatus() == ImageUploadStatus.COMPLETE)
.toList();
}

@Transactional(readOnly = true)
public MissionSummaryListResponse findSummaryList(LocalDate date) {
final Member currentMember = memberUtil.getCurrentMember();
List<Mission> missions =
missionRepository.findMissionsWithRecordsByDate(date, currentMember.getId());

List<MissionSummaryItem> result =
missions.stream()
.map(mission -> getMissionSummaryItem(mission))
.sorted(
Comparator.comparing(MissionSummaryItem::missionStatus)
.reversed()
.thenComparing(
Comparator.comparing(MissionSummaryItem::finishedAt)
.reversed()))
.collect(Collectors.toList());

result.sort(
Comparator.comparing(MissionSummaryItem::missionStatus)
.reversed()
.thenComparing(
Comparator.comparing(MissionSummaryItem::finishedAt).reversed()));

long missionAllCount = missions.size();
long missionCompleteCount =
result.stream()
.filter(
missionSummaryItem ->
missionSummaryItem.missionStatus()
== MissionStatus.COMPLETED)
.count();
long missionNoneCount = missionAllCount - missionCompleteCount;
return MissionSummaryListResponse.of(
missionAllCount, missionCompleteCount, missionNoneCount, result);
}

private static MissionSummaryItem getMissionSummaryItem(Mission mission) {
boolean isCompleted =
mission.getMissionRecords().stream()
.anyMatch(
missionRecord ->
missionRecord.getUploadStatus()
== ImageUploadStatus.COMPLETE);
return isCompleted
? MissionSummaryItem.of(mission, MissionStatus.COMPLETED)
: MissionSummaryItem.of(mission, MissionStatus.NONE);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.depromeet.domain.mission.dao;

import com.depromeet.domain.mission.domain.Mission;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

Expand All @@ -15,4 +16,6 @@ public interface MissionRepositoryCustom {
void updateFinishedDurationStatus(LocalDateTime today);

List<Mission> findAllFinishedMission(Long memberId);

List<Mission> findMissionsWithRecordsByDate(LocalDate date, Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -84,6 +85,22 @@ public List<Mission> findAllFinishedMission(Long memberId) {
.fetch();
}

@Override
public List<Mission> findMissionsWithRecordsByDate(LocalDate date, Long memberId) {
LocalDateTime startedAt = date.atTime(0, 0, 0);
LocalDateTime finishedAt = startedAt.plusDays(1);
JPAQuery<Mission> query =
jpaQueryFactory
.selectFrom(mission)
.leftJoin(mission.missionRecords, missionRecord)
.where(
memberIdEq(memberId),
mission.startedAt.loe(startedAt),
mission.finishedAt.goe(finishedAt))
.fetchJoin();
return query.fetch();
}

// 미션의 사용자 id 조건 검증 메서드
private BooleanExpression memberIdEq(Long memberId) {
return memberId == null ? null : mission.member.id.eq(memberId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.depromeet.domain.common.model.BaseTimeEntity;
import com.depromeet.domain.member.domain.Member;
import com.depromeet.domain.missionRecord.domain.ImageUploadStatus;
import com.depromeet.domain.missionRecord.domain.MissionRecord;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -127,8 +128,9 @@ public boolean isCompletedMissionToday() {
.filter(
record ->
record.getStartedAt()
.toLocalDate()
.equals(LocalDateTime.now().toLocalDate()))
.toLocalDate()
.equals(LocalDateTime.now().toLocalDate())
&& record.getUploadStatus() == ImageUploadStatus.COMPLETE)
.findFirst()
.isPresent();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.depromeet.domain.mission.dto.response;

import com.depromeet.domain.mission.domain.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;

public record MissionSummaryItem(
@Schema(description = "미션 ID", defaultValue = "1") Long missionId,
@Schema(description = "미션 이름", defaultValue = "default name") String name,
@Schema(description = "미션 카테고리", defaultValue = "STUDY") MissionCategory category,
@Schema(description = "미션 공개여부", defaultValue = "ALL") MissionVisibility visibility,
@Schema(description = "미션 상태", defaultValue = "1") MissionStatus missionStatus,
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd HH:mm:ss",
timezone = "Asia/Seoul")
@Schema(
description = "미션 종료 시간",
defaultValue = "2024-01-03 00:34:00",
type = "string")
LocalDateTime finishedAt) {

public static MissionSummaryItem of(Mission mission, MissionStatus missionStatus) {
return new MissionSummaryItem(
mission.getId(),
mission.getName(),
mission.getCategory(),
mission.getVisibility(),
missionStatus,
mission.getFinishedAt());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.depromeet.domain.mission.dto.response;

import java.util.List;

public record MissionSummaryListResponse(
long missionAllCount,
long missionCompleteCount,
long missionNoneCount,
List<MissionSummaryItem> missionSummaryItems) {
public static MissionSummaryListResponse of(
long missionAllCount,
long missionCompleteCount,
long missionNoneCount,
List<MissionSummaryItem> missionSummaryItems) {
return new MissionSummaryListResponse(
missionAllCount, missionCompleteCount, missionNoneCount, missionSummaryItems);
}
}

0 comments on commit c4bad25

Please sign in to comment.