Skip to content

Commit

Permalink
[WALWAL-174] raisepet mission supply (#168)
Browse files Browse the repository at this point in the history
* feature: Mission엔티티에 RaisePet추가 및 미션생성시 RaisePet설정

* feature: RaisePet에 따라 미션제공

* fix: QueryDsl로 변경

* fix: sonarcloud 이슈 수정
  • Loading branch information
dbscks97 authored Aug 21, 2024
1 parent 7fef5f6 commit a9f7c8a
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ public MissionGetTodayResponse getTodayMission() {
}

@GetMapping("/{missionId}")
public MissionGetOneResponse getMission(@PathVariable Long missionId) {
public MissionGetOneResponse getMission(@PathVariable("missionId") Long missionId) {
return missionService.getMission(missionId);
}

@PatchMapping("/{missionId}")
public MissionUpdateResponse updateMission(
@PathVariable Long missionId,
@PathVariable("missionId") Long missionId,
@Valid @RequestBody MissionUpdateRequest missionUpdateRequest) {
return missionService.updateMission(missionId, missionUpdateRequest);
}

@DeleteMapping("/{missionId}")
public void deleteMission(@PathVariable Long missionId) {
public void deleteMission(@PathVariable("missionId") Long missionId) {
missionService.deleteMission(missionId);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.depromeet.stonebed.domain.mission.application;

import com.depromeet.stonebed.domain.member.domain.Member;
import com.depromeet.stonebed.domain.member.domain.RaisePet;
import com.depromeet.stonebed.domain.mission.dao.mission.MissionRepository;
import com.depromeet.stonebed.domain.mission.dao.missionHistory.MissionHistoryRepository;
import com.depromeet.stonebed.domain.mission.domain.Mission;
Expand All @@ -12,6 +14,7 @@
import com.depromeet.stonebed.domain.mission.dto.response.MissionUpdateResponse;
import com.depromeet.stonebed.global.error.ErrorCode;
import com.depromeet.stonebed.global.error.exception.CustomException;
import com.depromeet.stonebed.global.util.MemberUtil;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.util.List;
Expand All @@ -26,11 +29,16 @@
public class MissionService {
private final MissionRepository missionRepository;
private final MissionHistoryRepository missionHistoryRepository;
private final MemberUtil memberUtil;
private final SecureRandom secureRandom = new SecureRandom();
private static final long MISSION_TODAY_STANDARD = 3;

public MissionCreateResponse createMission(MissionCreateRequest missionCreateRequest) {
Mission mission = Mission.builder().title(missionCreateRequest.title()).build();
Mission mission =
Mission.builder()
.title(missionCreateRequest.title())
.raisePet(missionCreateRequest.raisePet())
.build();

mission = missionRepository.save(mission);
return MissionCreateResponse.from(mission);
Expand All @@ -45,22 +53,26 @@ public MissionGetOneResponse getMission(Long missionId) {
}

public MissionGetTodayResponse getOrCreateTodayMission() {
final Member member = memberUtil.getCurrentMember();
final RaisePet raisePet = member.getRaisePet();
final LocalDate today = LocalDate.now();
LocalDate beforeDayByStandard = today.minusDays(MISSION_TODAY_STANDARD);

Optional<MissionHistory> findMissionHistory =
missionHistoryRepository.findByAssignedDate(today);
Optional<MissionHistory> existingMissionHistory =
missionHistoryRepository.findByAssignedDateAndRaisePet(today, raisePet);

if (findMissionHistory.isPresent()) {
return MissionGetTodayResponse.from(findMissionHistory.get().getMission());
if (existingMissionHistory.isPresent()) {
return MissionGetTodayResponse.from(existingMissionHistory.get().getMission());
}

// 최근 3일 내의 미션들 불러오기
// 최근 3일 내의 미션들 중 현재 회원의 반려동물 유형에 맞는 미션들만 불러오기
List<Mission> recentMissions =
missionRepository.findMissionsAssignedAfter(beforeDayByStandard);
missionRepository.findMissionsAssignedAfterAndByRaisePet(
beforeDayByStandard, raisePet);

// 최근 3일 이내의 미션은 제외하고 불러오기
List<Mission> availableMissions = missionRepository.findNotInMissions(recentMissions);
// 최근 3일 이내의 미션을 제외하고 현재 회원의 반려동물 유형에 맞는 미션들 불러오기
List<Mission> availableMissions =
missionRepository.findNotInMissionsAndByRaisePet(recentMissions, raisePet);

if (availableMissions.isEmpty()) {
throw new CustomException(ErrorCode.NO_AVAILABLE_TODAY_MISSION);
Expand All @@ -84,6 +96,7 @@ public MissionUpdateResponse updateMission(
.orElseThrow(() -> new CustomException(ErrorCode.MISSION_NOT_FOUND));

missionToUpdate.updateTitle(missionUpdateRequest.title());
missionToUpdate.updateRaisePet(missionUpdateRequest.raisePet());
missionRepository.save(missionToUpdate);

return MissionUpdateResponse.from(missionToUpdate);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.depromeet.stonebed.domain.mission.dao.mission;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import com.depromeet.stonebed.domain.mission.domain.Mission;
import java.time.LocalDate;
import java.util.List;

public interface MissionRepositoryCustom {
List<Mission> findNotInMissions(List<Mission> missions);
List<Mission> findMissionsAssignedAfterAndByRaisePet(LocalDate assignedDate, RaisePet raisePet);

List<Mission> findMissionsAssignedAfter(LocalDate assignedDate);
List<Mission> findNotInMissionsAndByRaisePet(List<Mission> missions, RaisePet raisePet);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static com.depromeet.stonebed.domain.mission.domain.QMission.mission;
import static com.depromeet.stonebed.domain.mission.domain.QMissionHistory.missionHistory;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import com.depromeet.stonebed.domain.mission.domain.Mission;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
Expand All @@ -17,16 +18,21 @@ public class MissionRepositoryImpl implements MissionRepositoryCustom {
private final JPAQueryFactory queryFactory;

@Override
public List<Mission> findNotInMissions(List<Mission> missions) {
return queryFactory.selectFrom(mission).where(mission.notIn(missions)).fetch();
public List<Mission> findNotInMissionsAndByRaisePet(List<Mission> missions, RaisePet raisePet) {
return queryFactory
.selectFrom(mission)
.where(mission.notIn(missions).and(mission.raisePet.eq(raisePet)))
.fetch();
}

@Override
public List<Mission> findMissionsAssignedAfter(LocalDate assignedDate) {
public List<Mission> findMissionsAssignedAfterAndByRaisePet(
LocalDate assignedDate, RaisePet raisePet) {
return queryFactory
.select(missionHistory.mission)
.from(missionHistory)
.where(assignedDateAfter(assignedDate))
.join(missionHistory.mission, mission)
.where(assignedDateAfter(assignedDate).and(mission.raisePet.eq(raisePet)))
.fetch();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

import com.depromeet.stonebed.domain.mission.domain.MissionHistory;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MissionHistoryRepository
extends JpaRepository<MissionHistory, Long>, MissionHistoryRepositoryCustom {
Optional<MissionHistory> findByAssignedDate(LocalDate date);

List<MissionHistory> findByAssignedDateBefore(LocalDate date);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.depromeet.stonebed.domain.mission.dao.missionHistory;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import com.depromeet.stonebed.domain.mission.domain.MissionHistory;
import java.time.LocalDate;
import java.util.Optional;

public interface MissionHistoryRepositoryCustom {
Optional<MissionHistory> findLatestOneByMissionId(Long missionId);

Optional<MissionHistory> findByAssignedDateAndRaisePet(LocalDate date, RaisePet raisePet);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import static com.depromeet.stonebed.domain.mission.domain.QMissionHistory.missionHistory;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import com.depromeet.stonebed.domain.mission.domain.MissionHistory;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.time.LocalDate;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -22,4 +24,18 @@ public Optional<MissionHistory> findLatestOneByMissionId(Long missionId) {
.orderBy(missionHistory.assignedDate.desc())
.fetchFirst());
}

@Override
public Optional<MissionHistory> findByAssignedDateAndRaisePet(
LocalDate date, RaisePet raisePet) {
return Optional.ofNullable(
queryFactory
.selectFrom(missionHistory)
.where(
missionHistory
.assignedDate
.eq(date)
.and(missionHistory.mission.raisePet.eq(raisePet)))
.fetchFirst());
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.depromeet.stonebed.domain.mission.domain;

import com.depromeet.stonebed.domain.common.BaseTimeEntity;
import com.depromeet.stonebed.domain.member.domain.RaisePet;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -27,9 +30,14 @@ public class Mission extends BaseTimeEntity {
@Column(name = "illustration_url")
private String illustrationUrl;

@Enumerated(EnumType.STRING)
@Column(name = "raise_pet", nullable = false)
private RaisePet raisePet;

@Builder
public Mission(String title) {
public Mission(String title, RaisePet raisePet) {
this.title = title;
this.raisePet = raisePet;
}

public void updateTitle(String title) {
Expand All @@ -39,4 +47,8 @@ public void updateTitle(String title) {
public void updateIllustrationUrl(String illustrationUrl) {
this.illustrationUrl = illustrationUrl;
}

public void updateRaisePet(RaisePet raisePet) {
this.raisePet = raisePet;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(
name = "mission_history",
uniqueConstraints = {@UniqueConstraint(columnNames = {"assigned_date", "mission_id"})})
public class MissionHistory extends BaseTimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -21,7 +24,7 @@ public class MissionHistory extends BaseTimeEntity {
@JoinColumn(name = "mission_id", nullable = false)
private Mission mission;

@Column(name = "assigned_date", nullable = false, unique = true)
@Column(name = "assigned_date", nullable = false)
private LocalDate assignedDate;

@Builder(access = AccessLevel.PRIVATE)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.depromeet.stonebed.domain.mission.dto.request;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record MissionCreateRequest(
@Schema(description = "미션 제목", example = "산책하기")
@NotBlank(message = "Title cannot be blank")
String title) {}
String title,
@Schema(description = "반려동물 유형", example = "DOG")
@NotNull(message = "RaisePet cannot be null")
RaisePet raisePet) {}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.depromeet.stonebed.domain.mission.dto.request;

import com.depromeet.stonebed.domain.member.domain.RaisePet;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

public record MissionUpdateRequest(
@Schema(description = "미션 제목", example = "산책하기")
@NotBlank(message = "Title cannot be blank")
String title) {}
String title,
@Schema(description = "반려동물 유형", example = "DOG")
@NotNull(message = "RaisePet cannot be null")
RaisePet raisePet) {}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void setUp() {
mockMvc.perform(
post("/missions")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"title\":\"Test Mission\"}"))
.content("{\"title\":\"Test Mission\", \"raisePet\":\"DOG\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.title").value("Test Mission"));
}
Expand Down Expand Up @@ -93,7 +93,7 @@ public void setUp() {
mockMvc.perform(
patch("/missions/1")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"title\":\"Updated Mission\"}"))
.content("{\"title\":\"Test Mission\", \"raisePet\":\"DOG\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.title").value("Updated Mission"));
}
Expand Down
Loading

0 comments on commit a9f7c8a

Please sign in to comment.