diff --git a/src/main/java/com/sillim/recordit/goal/controller/GoalController.java b/src/main/java/com/sillim/recordit/goal/controller/GoalController.java new file mode 100644 index 0000000..781acc6 --- /dev/null +++ b/src/main/java/com/sillim/recordit/goal/controller/GoalController.java @@ -0,0 +1,38 @@ +package com.sillim.recordit.goal.controller; + +import com.sillim.recordit.config.security.authenticate.CurrentMember; +import com.sillim.recordit.goal.domain.MonthlyGoal; +import com.sillim.recordit.goal.domain.WeeklyGoal; +import com.sillim.recordit.goal.dto.response.GoalListResponse; +import com.sillim.recordit.goal.service.MonthlyGoalQueryService; +import com.sillim.recordit.goal.service.WeeklyGoalQueryService; +import com.sillim.recordit.member.domain.Member; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/goals") +public class GoalController { + + private final MonthlyGoalQueryService monthlyGoalQueryService; + private final WeeklyGoalQueryService weeklyGoalQueryService; + + @GetMapping + public ResponseEntity getGoalListByDate( + @RequestParam final Integer year, + @RequestParam final Integer month, + @CurrentMember final Member member) { + + List monthlyGoals = + monthlyGoalQueryService.searchAllByDate(year, month, member.getId()); + List weeklyGoals = + weeklyGoalQueryService.searchAllWeeklyGoalByDate(year, month, member.getId()); + return ResponseEntity.ok(GoalListResponse.of(monthlyGoals, weeklyGoals)); + } +} diff --git a/src/main/java/com/sillim/recordit/goal/dto/response/GoalListResponse.java b/src/main/java/com/sillim/recordit/goal/dto/response/GoalListResponse.java new file mode 100644 index 0000000..372a178 --- /dev/null +++ b/src/main/java/com/sillim/recordit/goal/dto/response/GoalListResponse.java @@ -0,0 +1,17 @@ +package com.sillim.recordit.goal.dto.response; + +import com.sillim.recordit.goal.domain.MonthlyGoal; +import com.sillim.recordit.goal.domain.WeeklyGoal; +import java.util.List; + +public record GoalListResponse(List monthlyGoals, List weeklyGoals) { + + public static GoalListResponse of( + final List monthlyGoals, final List weeklyGoals) { + List monthlyGoalResponses = + monthlyGoals.stream().map(GoalResponse::from).toList(); + List weeklyGoalResponses = + weeklyGoals.stream().map(GoalResponse::from).toList(); + return new GoalListResponse(monthlyGoalResponses, weeklyGoalResponses); + } +} diff --git a/src/main/java/com/sillim/recordit/goal/dto/response/GoalResponse.java b/src/main/java/com/sillim/recordit/goal/dto/response/GoalResponse.java new file mode 100644 index 0000000..d91887a --- /dev/null +++ b/src/main/java/com/sillim/recordit/goal/dto/response/GoalResponse.java @@ -0,0 +1,15 @@ +package com.sillim.recordit.goal.dto.response; + +import com.sillim.recordit.goal.domain.MonthlyGoal; +import com.sillim.recordit.goal.domain.WeeklyGoal; + +public record GoalResponse(Long id, String title) { + + public static GoalResponse from(final MonthlyGoal monthlyGoal) { + return new GoalResponse(monthlyGoal.getId(), monthlyGoal.getTitle()); + } + + public static GoalResponse from(final WeeklyGoal weeklyGoal) { + return new GoalResponse(weeklyGoal.getId(), weeklyGoal.getTitle()); + } +} diff --git a/src/main/java/com/sillim/recordit/task/service/TaskGroupService.java b/src/main/java/com/sillim/recordit/task/service/TaskGroupService.java index 3c544b3..0254f60 100644 --- a/src/main/java/com/sillim/recordit/task/service/TaskGroupService.java +++ b/src/main/java/com/sillim/recordit/task/service/TaskGroupService.java @@ -6,6 +6,7 @@ import com.sillim.recordit.goal.domain.WeeklyGoal; import com.sillim.recordit.goal.dto.RelatedGoals; import com.sillim.recordit.goal.service.MonthlyGoalQueryService; +import com.sillim.recordit.goal.service.WeeklyGoalQueryService; import com.sillim.recordit.task.domain.TaskGroup; import com.sillim.recordit.task.domain.repetition.TaskRepetitionPatternFactory; import com.sillim.recordit.task.dto.request.TaskGroupUpdateRequest; @@ -21,7 +22,7 @@ public class TaskGroupService { private final MonthlyGoalQueryService monthlyGoalQueryService; - // TODO: WeeklyGoal 기능 구현 후 추가 필요 + private final WeeklyGoalQueryService weeklyGoalQueryService; private final TaskGroupRepository taskGroupRepository; @@ -137,7 +138,8 @@ private RelatedGoals getRelatedGoals( return RelatedGoals.empty(); } if (monthlyGoalId == null) { - WeeklyGoal weeklyGoal = null; + WeeklyGoal weeklyGoal = + weeklyGoalQueryService.searchByIdAndCheckAuthority(weeklyGoalId, memberId); return RelatedGoals.from(weeklyGoal); } if (weeklyGoalId == null) { @@ -147,7 +149,8 @@ private RelatedGoals getRelatedGoals( } MonthlyGoal monthlyGoal = monthlyGoalQueryService.searchByIdAndCheckAuthority(monthlyGoalId, memberId); - WeeklyGoal weeklyGoal = null; + WeeklyGoal weeklyGoal = + weeklyGoalQueryService.searchByIdAndCheckAuthority(weeklyGoalId, memberId); return RelatedGoals.of(monthlyGoal, weeklyGoal); } } diff --git a/src/test/java/com/sillim/recordit/goal/controller/GoalControllerTest.java b/src/test/java/com/sillim/recordit/goal/controller/GoalControllerTest.java new file mode 100644 index 0000000..2cb778a --- /dev/null +++ b/src/test/java/com/sillim/recordit/goal/controller/GoalControllerTest.java @@ -0,0 +1,111 @@ +package com.sillim.recordit.goal.controller; + +import static com.sillim.recordit.support.restdocs.ApiDocumentUtils.getDocumentRequest; +import static com.sillim.recordit.support.restdocs.ApiDocumentUtils.getDocumentResponse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.spy; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.queryParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.sillim.recordit.goal.domain.MonthlyGoal; +import com.sillim.recordit.goal.domain.WeeklyGoal; +import com.sillim.recordit.goal.fixture.MonthlyGoalFixture; +import com.sillim.recordit.goal.fixture.WeeklyGoalFixture; +import com.sillim.recordit.goal.service.MonthlyGoalQueryService; +import com.sillim.recordit.goal.service.WeeklyGoalQueryService; +import com.sillim.recordit.member.domain.Member; +import com.sillim.recordit.member.fixture.MemberFixture; +import com.sillim.recordit.support.restdocs.RestDocsTest; +import java.util.List; +import java.util.stream.LongStream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.ResultActions; + +@WebMvcTest(GoalController.class) +public class GoalControllerTest extends RestDocsTest { + + @MockBean MonthlyGoalQueryService monthlyGoalQueryService; + @MockBean WeeklyGoalQueryService weeklyGoalQueryService; + + private Member member; + + @BeforeEach + void beforeEach() { + member = MemberFixture.DEFAULT.getMember(); + } + + @Test + @DisplayName("당월의 목표 목록을 조회한다.") + void monthlyGoalListTest() throws Exception { + List monthlyGoals = + LongStream.rangeClosed(1, 3) + .mapToObj( + (id) -> { + MonthlyGoal goal = + spy(MonthlyGoalFixture.DEFAULT.getWithMember(member)); + given(goal.getId()).willReturn(id); + given(goal.isAchieved()).willReturn(id % 2 == 0); + return goal; + }) + .toList(); + given(monthlyGoalQueryService.searchAllByDate(anyInt(), anyInt(), any())) + .willReturn(monthlyGoals); + List weeklyGoals = + LongStream.rangeClosed(1, 2) + .mapToObj( + (id) -> { + WeeklyGoal goal = + spy(WeeklyGoalFixture.DEFAULT.getWithMember(member)); + given(goal.getId()).willReturn(id); + given(goal.isAchieved()).willReturn(id % 2 == 0); + return goal; + }) + .toList(); + given(weeklyGoalQueryService.searchAllWeeklyGoalByDate(anyInt(), anyInt(), any())) + .willReturn(weeklyGoals); + + ResultActions perform = + mockMvc.perform( + get("/api/v1/goals") + .headers(authorizationHeader()) + .queryParam("year", "2024") + .queryParam("month", "4")); + + perform.andExpect(status().isOk()) + .andExpect(jsonPath("$.monthlyGoals.size()").value(3)) + .andExpect(jsonPath("$.weeklyGoals.size()").value(2)) + .andExpect(jsonPath("$.monthlyGoals.[0].id").value(1)) + .andExpect(jsonPath("$.monthlyGoals.[0].title").value("취뽀하기!")) + .andExpect(jsonPath("$.monthlyGoals.[1].id").value(2)) + .andExpect(jsonPath("$.monthlyGoals.[1].title").value("취뽀하기!")) + .andExpect(jsonPath("$.monthlyGoals.[2].id").value(3)) + .andExpect(jsonPath("$.monthlyGoals.[2].title").value("취뽀하기!")) + .andExpect(jsonPath("$.weeklyGoals.[0].id").value(1)) + .andExpect(jsonPath("$.weeklyGoals.[0].title").value("데이터베이스 3장까지")) + .andExpect(jsonPath("$.weeklyGoals.[1].id").value(2)) + .andExpect(jsonPath("$.weeklyGoals.[1].title").value("데이터베이스 3장까지")); + + perform.andDo(print()) + .andDo( + document( + "goal-list", + getDocumentRequest(), + getDocumentResponse(), + requestHeaders(authorizationDesc()), + queryParameters( + parameterWithName("year").description("조회할 연도"), + parameterWithName("month").description("조회할 월")))); + } +} diff --git a/src/test/java/com/sillim/recordit/task/service/TaskGroupServiceTest.java b/src/test/java/com/sillim/recordit/task/service/TaskGroupServiceTest.java index 85ad834..8d1813a 100644 --- a/src/test/java/com/sillim/recordit/task/service/TaskGroupServiceTest.java +++ b/src/test/java/com/sillim/recordit/task/service/TaskGroupServiceTest.java @@ -11,6 +11,7 @@ import com.sillim.recordit.goal.domain.MonthlyGoal; import com.sillim.recordit.goal.domain.WeeklyGoal; import com.sillim.recordit.goal.service.MonthlyGoalQueryService; +import com.sillim.recordit.goal.service.WeeklyGoalQueryService; import com.sillim.recordit.task.domain.TaskGroup; import com.sillim.recordit.task.domain.TaskRepetitionType; import com.sillim.recordit.task.domain.repetition.TaskRepetitionPattern; @@ -34,6 +35,7 @@ class TaskGroupServiceTest { @InjectMocks TaskGroupService taskGroupService; @Mock TaskGroupRepository taskGroupRepository; @Mock MonthlyGoalQueryService monthlyGoalQueryService; + @Mock WeeklyGoalQueryService weeklyGoalQueryService; // TODO: WeeklyGoal 기능 구현 후 테스트 추가 필요