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 @@ -7,7 +7,6 @@
import com.ject.studytrip.mission.domain.repository.DailyMissionQueryRepository;
import com.ject.studytrip.mission.domain.repository.DailyMissionRepository;
import com.ject.studytrip.trip.domain.model.DailyGoal;
import com.ject.studytrip.trip.domain.model.TripCategory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -45,27 +44,7 @@ public List<DailyMission> getValidDailyMissionsByIds(
return dailyMissions;
}

public List<DailyMission> getValidDailyMissionByIdsWithMissionAndStamp(
Long dailyGoalId, List<Long> dailyMissionIds) {
List<DailyMission> dailyMissions =
dailyMissionQueryRepository.findAllByIdsFetchJoinMissionAndStamp(dailyMissionIds);

DailyMissionPolicy.validateExistAll(dailyMissions, dailyMissionIds);
dailyMissions.forEach(
dailyMission -> {
DailyMissionPolicy.validateBelongsToDailyGoal(dailyMission, dailyGoalId);
DailyMissionPolicy.validateNotDeleted(dailyMission);
});

return dailyMissions;
}

public List<DailyMission> getDailyMissionsByDailyGoal(Long dailyGoalId) {
return dailyMissionQueryRepository.findAllByDailyGoalIdFetchJoinMission(dailyGoalId);
}

public void validateSelectedDailyMissions(
TripCategory tripCategory, List<DailyMission> dailyMissions) {
DailyMissionPolicy.validateCourseTripStampConsistency(tripCategory, dailyMissions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ public void completeMission(Mission mission) {
mission.updateCompleted();
}

public void validateMissionBelongsToStamp(Long stampId, Mission mission) {
MissionPolicy.validateMissionBelongsToStamp(stampId, mission);
public void validateMissionsBelongsToStamp(Long stampId, List<Mission> missions) {
for (Mission mission : missions) {
MissionPolicy.validateMissionBelongsToStamp(stampId, mission);
}
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
public enum DailyMissionErrorCode implements ErrorCode {
// 400
DAILY_MISSION_ALREADY_DELETED(HttpStatus.BAD_REQUEST, "이미 삭제된 데일리 미션입니다."),
COURSE_TRIP_STAMP_MISMATCH(HttpStatus.BAD_REQUEST, "코스형 여행의 데일리 미션들은 모두 동일한 스탬프여야 합니다."),

// 403
DAILY_MISSION_NOT_BELONG_TO_DAILY_GOAL(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import com.ject.studytrip.global.exception.CustomException;
import com.ject.studytrip.mission.domain.error.DailyMissionErrorCode;
import com.ject.studytrip.mission.domain.model.DailyMission;
import com.ject.studytrip.trip.domain.model.TripCategory;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

Expand All @@ -27,18 +24,4 @@ public static void validateNotDeleted(DailyMission dailyMission) {
if (dailyMission.getDeletedAt() != null)
throw new CustomException(DailyMissionErrorCode.DAILY_MISSION_ALREADY_DELETED);
}

public static void validateCourseTripStampConsistency(
TripCategory tripCategory, List<DailyMission> dailyMissions) {
if (tripCategory != TripCategory.COURSE) return;

Set<Long> stampIds =
dailyMissions.stream()
.map(dailyMission -> dailyMission.getMission().getStamp().getId())
.collect(Collectors.toSet());

if (stampIds.size() != 1) {
throw new CustomException(DailyMissionErrorCode.COURSE_TRIP_STAMP_MISMATCH);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@

public interface DailyMissionQueryRepository {
List<DailyMission> findAllByDailyGoalIdFetchJoinMission(Long dailyGoalId);

List<DailyMission> findAllByIdsFetchJoinMissionAndStamp(List<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.ject.studytrip.mission.domain.model.QDailyMission;
import com.ject.studytrip.mission.domain.model.QMission;
import com.ject.studytrip.mission.domain.repository.DailyMissionQueryRepository;
import com.ject.studytrip.stamp.domain.model.QStamp;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -16,7 +15,6 @@ public class DailyMissionQueryRepositoryAdapter implements DailyMissionQueryRepo
private final JPAQueryFactory queryFactory;
private final QDailyMission dailyMission = QDailyMission.dailyMission;
private final QMission mission = QMission.mission;
private final QStamp stamp = QStamp.stamp;

@Override
public List<DailyMission> findAllByDailyGoalIdFetchJoinMission(Long dailyGoalId) {
Expand All @@ -27,16 +25,4 @@ public List<DailyMission> findAllByDailyGoalIdFetchJoinMission(Long dailyGoalId)
.where(dailyMission.dailyGoal.id.eq(dailyGoalId), dailyMission.deletedAt.isNull())
.fetch();
}

@Override
public List<DailyMission> findAllByIdsFetchJoinMissionAndStamp(List<Long> ids) {
return queryFactory
.selectFrom(dailyMission)
.join(dailyMission.mission, mission)
.fetchJoin()
.join(mission.stamp, stamp)
.fetchJoin()
.where(dailyMission.id.in(ids))
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ public String getStampNameByTripCategory(TripCategory tripCategory, List<Stamp>
stamps.forEach(StampPolicy::validateNotDeleted);

if (tripCategory == TripCategory.COURSE) {
return getCourseStampName(stamps);
// 코스형 여행은 상위 검증에서 동일한 스탬프인지 검증이 완료된 상태이므로
// 스탬프 리스트에서 첫 번째 스탬프의 이름을 추출해도 안전
return stamps.get(0).getName();
}

return getExplorationStampName(stamps);
Expand All @@ -152,10 +154,6 @@ public void validateAllStampsCompletedByTripId(Long tripId) {
StampPolicy.validateAllCompleted(exists);
}

private String getCourseStampName(List<Stamp> stamps) {
return new HashSet<>(stamps).iterator().next().getName();
}

private String getExplorationStampName(List<Stamp> stamps) {
// 스탬프별 개수 집계
Map<Stamp, Long> stampCountMap =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package com.ject.studytrip.studylog.application.facade;

import com.ject.studytrip.member.domain.model.Member;
import com.ject.studytrip.mission.application.service.DailyMissionService;
import com.ject.studytrip.mission.application.service.MissionService;
import com.ject.studytrip.mission.domain.model.DailyMission;
import com.ject.studytrip.pomodoro.application.service.PomodoroService;
import com.ject.studytrip.stamp.application.service.StampService;
import com.ject.studytrip.stamp.domain.model.Stamp;
import com.ject.studytrip.studylog.application.dto.StudyLogDetail;
import com.ject.studytrip.studylog.application.dto.StudyLogInfo;
import com.ject.studytrip.studylog.application.service.StudyLogDailyMissionService;
Expand All @@ -18,7 +15,6 @@
import com.ject.studytrip.trip.application.service.TripService;
import com.ject.studytrip.trip.domain.model.DailyGoal;
import com.ject.studytrip.trip.domain.model.Trip;
import com.ject.studytrip.trip.domain.model.TripCategory;
import java.util.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Slice;
Expand All @@ -30,7 +26,6 @@
@RequiredArgsConstructor
public class StudyLogFacade {
private final TripService tripService;
private final StampService stampService;
private final MissionService missionService;
private final DailyGoalService dailyGoalService;
private final DailyMissionService dailyMissionService;
Expand All @@ -45,16 +40,12 @@ public StudyLogInfo createStudyLog(
Trip trip = tripService.getValidTrip(memberId, tripId);
DailyGoal dailyGoal = dailyGoalService.getValidDailyGoal(trip.getId(), dailyGoalId);
List<DailyMission> selectedDailyMissions =
getValidatedDailyMissions(dailyGoal.getId(), request);
dailyMissionService.getValidDailyMissionsByIds(
dailyGoal.getId(), request.selectedDailyMissionIds());

// 2. 학습 로그 생성
StudyLog studyLog =
createStudyLogWithTitle(
trip.getMember(),
dailyGoal,
trip.getCategory(),
selectedDailyMissions,
request);
studyLogService.createStudyLog(trip.getMember(), dailyGoal, request.content());

// 3. 뽀모도로 총 학습시간 업데이트
pomodoroService.updateTotalFocusTime(dailyGoalId, request.totalFocusTimeInMinutes());
Expand All @@ -65,36 +56,6 @@ public StudyLogInfo createStudyLog(
return StudyLogInfo.from(studyLog);
}

private List<DailyMission> getValidatedDailyMissions(
Long dailyGoalId, CreateStudyLogRequest request) {
List<DailyMission> selectedDailyMissions =
dailyMissionService.getValidDailyMissionByIdsWithMissionAndStamp(
dailyGoalId, request.selectedDailyMissionIds());
dailyMissionService.validateSelectedDailyMissions(
TripCategory.COURSE, selectedDailyMissions);
return selectedDailyMissions;
}

private StudyLog createStudyLogWithTitle(
Member member,
DailyGoal dailyGoal,
TripCategory tripCategory,
List<DailyMission> selectedDailyMissions,
CreateStudyLogRequest request) {
String title = determineTitleByStamps(tripCategory, selectedDailyMissions);
return studyLogService.createStudyLog(member, dailyGoal, title, request.content());
}

private String determineTitleByStamps(
TripCategory tripCategory, List<DailyMission> selectedDailyMissions) {
List<Stamp> stamps =
selectedDailyMissions.stream()
.map(dailyMission -> dailyMission.getMission().getStamp())
.toList();

return stampService.getStampNameByTripCategory(tripCategory, stamps);
}

private void createStudyLogDailyMissionsAndCompleteMissions(
StudyLog studyLog, List<DailyMission> selectedDailyMissions) {
// 학습 로그 데일리 미션 저장
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ public long getActiveStudyLogCountByMemberId(Long memberId) {
return studyLogQueryRepository.countActiveStudyLogsByMemberId(memberId);
}

public StudyLog createStudyLog(
Member member, DailyGoal dailyGoal, String title, String content) {
StudyLog studyLog = StudyLogFactory.create(member, dailyGoal, title, content);
public StudyLog createStudyLog(Member member, DailyGoal dailyGoal, String content) {
StudyLog studyLog = StudyLogFactory.create(member, dailyGoal, content);
return studyLogRepository.save(studyLog);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StudyLogFactory {
public static StudyLog create(
Member member, DailyGoal dailyGoal, String title, String content) {
return StudyLog.of(member, dailyGoal, title, content);
public static StudyLog create(Member member, DailyGoal dailyGoal, String content) {
return StudyLog.of(member, dailyGoal, content);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ public class StudyLog extends BaseTimeEntity {
@Column(nullable = false)
private String content;

public static StudyLog of(Member member, DailyGoal dailyGoal, String title, String content) {
public static StudyLog of(Member member, DailyGoal dailyGoal, String content) {
return StudyLog.builder()
.member(member)
.dailyGoal(dailyGoal)
.title(title)
.title(dailyGoal.getTitle())
.content(content)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
import com.ject.studytrip.trip.domain.model.DailyGoal;

public record DailyGoalInfo(
Long dailyGoalId, boolean completed, String createdAt, String updatedAt, String deletedAt) {
Long dailyGoalId,
String title,
boolean completed,
String createdAt,
String updatedAt,
String deletedAt) {
public static DailyGoalInfo from(DailyGoal dailyGoal) {
return new DailyGoalInfo(
dailyGoal.getId(),
dailyGoal.getTitle(),
dailyGoal.isCompleted(),
DateUtil.formatDateTime(dailyGoal.getCreatedAt()),
DateUtil.formatDateTime(dailyGoal.getUpdatedAt()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.ject.studytrip.pomodoro.application.service.PomodoroService;
import com.ject.studytrip.pomodoro.domain.model.Pomodoro;
import com.ject.studytrip.stamp.application.service.StampService;
import com.ject.studytrip.stamp.domain.model.Stamp;
import com.ject.studytrip.trip.application.dto.DailyGoalDetail;
import com.ject.studytrip.trip.application.dto.DailyGoalInfo;
import com.ject.studytrip.trip.application.service.DailyGoalService;
Expand Down Expand Up @@ -40,12 +41,13 @@ public class DailyGoalFacade {
public DailyGoalInfo createDailyGoal(
Long memberId, Long tripId, CreateDailyGoalRequest request) {
Trip trip = getValidTripOwnedByMember(memberId, tripId);
List<Mission> missions = getValidMissionsByTripCategory(trip, request.missionIds());

DailyGoal dailyGoal = dailyGoalService.createDailyGoal(trip);
// 스탬프 이름을 추출해 title 설정
String title = determineTitleByStamps(trip.getCategory(), missions);
DailyGoal dailyGoal = dailyGoalService.createDailyGoal(trip, title);

List<Mission> missions = getValidMissionsByTripCategory(trip, request.missionIds());
dailyMissionService.createDailyMissions(dailyGoal, missions);

pomodoroService.createPomodoro(dailyGoal, request.pomodoro());

return DailyGoalInfo.from(dailyGoal);
Expand Down Expand Up @@ -128,11 +130,15 @@ private List<Mission> getValidMissionsByTripCategory(Trip trip, List<Long> missi
Long currentStampId =
stampService.getFirstInCompleteStampForCourseTrip(trip.getId()).getId();

for (Mission mission : missions) {
missionService.validateMissionBelongsToStamp(currentStampId, mission);
}
missionService.validateMissionsBelongsToStamp(currentStampId, missions);
}

return missions;
}

private String determineTitleByStamps(TripCategory tripCategory, List<Mission> missions) {
List<Stamp> stamps = missions.stream().map(Mission::getStamp).toList();

return stampService.getStampNameByTripCategory(tripCategory, stamps);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
public class DailyGoalService {
public final DailyGoalRepository dailyGoalRepository;

public DailyGoal createDailyGoal(Trip trip) {
DailyGoal dailyGoal = DailyGoalFactory.create(trip);
public DailyGoal createDailyGoal(Trip trip, String title) {
DailyGoal dailyGoal = DailyGoalFactory.create(trip, title);
return dailyGoalRepository.save(dailyGoal);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DailyGoalFactory {
public static DailyGoal create(Trip trip) {
return DailyGoal.of(trip);
public static DailyGoal create(Trip trip, String title) {
return DailyGoal.of(trip, title);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ public class DailyGoal extends BaseTimeEntity {
@JoinColumn(name = "trip_id", nullable = false)
private Trip trip;

@Column(nullable = false)
private String title;

private boolean completed;

public static DailyGoal of(Trip trip) {
return DailyGoal.builder().trip(trip).completed(false).build();
public static DailyGoal of(Trip trip, String title) {
return DailyGoal.builder().trip(trip).title(title).completed(false).build();
}

public void updateDeletedAt() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

public record LoadDailyGoalDetailResponse(
@Schema(name = "데일리 목표 ID") Long dailyGoalId,
@Schema(name = "데일리 목표 제목(스탬프 이름)") String title,
@Schema(name = "데일리 목표 완료 여부") boolean completed,
@Schema(name = "뽀모도로 정보") DailyGoalPomodoroResponse pomodoro,
@Schema(name = "수행할 데일리 미션 목록") List<DailyGoalMissionResponse> dailyMissions) {
Expand All @@ -18,6 +19,7 @@ public static LoadDailyGoalDetailResponse of(
List<DailyMissionInfo> dailyMissionInfos) {
return new LoadDailyGoalDetailResponse(
dailyGoalInfo.dailyGoalId(),
dailyGoalInfo.title(),
dailyGoalInfo.completed(),
DailyGoalPomodoroResponse.of(pomodoroInfo),
dailyMissionInfos.stream().map(DailyGoalMissionResponse::of).toList());
Expand Down
Loading