Skip to content

Commit

Permalink
feat/124: 실행 목표 조회 API 구현 (#129)
Browse files Browse the repository at this point in the history
* feat: 스페이스의 완료 회고중 가장 최근에 시작된 회고의 액션 아이템 리스트 조회 구현

* chore: 최근 회고의 기준을 데드라인으로 변경

* chore: swagger에 설명 추가

* feat: 스페이스의 모든 실행 목표 API 조회 구현

* feat: 멤버의 실행 목표 controller, service 메서드 생성

* feat: 실행 목표 create, member와 관련한 실행 목표 조회 구현

* chore: 응답 변수명 변경

* chore: application-dev 수정

* chore: 멤버 실천 목표 응답 수정

* feat: 멤버 실행 목표 핀, 상태 기준 정렬 구현

* chore: 조회 DTO 이름 변경(prefix get 추가)
  • Loading branch information
clean2001 authored Aug 5, 2024
1 parent 8238707 commit 2fc3927
Show file tree
Hide file tree
Showing 19 changed files with 338 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,22 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.layer.common.annotation.MemberId;
import org.layer.domain.actionItem.controller.dto.CreateActionItemRequest;
import org.layer.domain.actionItem.controller.dto.CreateActionItemResponse;
import org.layer.domain.actionItem.controller.dto.DeleteActionItemResponse;
import org.layer.domain.actionItem.controller.dto.MemberActionItemResponse;
import org.layer.domain.actionItem.controller.dto.SpaceActionItemElementResponse;
import org.layer.domain.actionItem.controller.dto.SpaceActionItemResponse;
import org.layer.domain.actionItem.controller.dto.*;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@Tag(name = "액션아이템 API")
public interface ActionItemApi {
@Operation(summary = "액션 아이템 생성", method = "POST", description = """
특정 회고와 매핑되는 액션 아이템을 생성합니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "201",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = CreateActionItemResponse.class)
)
}
)
@ApiResponse(responseCode = "201")
}
)
ResponseEntity<CreateActionItemResponse> createActionItem(@MemberId Long memberId,
ResponseEntity<Void> createActionItem(@MemberId Long memberId,
@Validated @RequestBody CreateActionItemRequest createActionItemRequest);


Expand All @@ -54,11 +40,30 @@ ResponseEntity<CreateActionItemResponse> createActionItem(@MemberId Long memberI
)
}
)
ResponseEntity<List<MemberActionItemResponse>> memberActionItem(@MemberId Long currentMemberId,
Long memberId);
ResponseEntity<MemberActionItemResponse> memberActionItem(@MemberId Long currentMemberId);

@Operation(summary = "팀의 액션 아이템 조회", method = "GET", description = """
팀 아이디로 팀의 모든 액션아이템을 조회합니다.
팀 아이디로 팀의 모든 액션아이템을 회고 별로 조회합니다.
정렬 기준: 최신순(데드라인 내림차순)
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
content = {
@Content(
mediaType = "application/json",
schema = @Schema(implementation = SpaceActionItemElementResponse.class)
)
}
)
}
)
ResponseEntity<GetSpaceRetrospectActionItemResponse> teamActionItem(@MemberId Long memberId,
@PathVariable Long spaceId);


@Operation(summary = "스페이스의 가장 최근 회고의 실행 목표 조회", method = "GET", description = """
특정 스페이스에서 완료된 가장 최근 회고(데드라인 기준)를 찾고, 그 회고의 실행 목표 목록을 조회합니다.
해당 스페이스에서 아직 완료된 회고가 없다면 null이 반환됩니다.
""")
@ApiResponses({
@ApiResponse(responseCode = "200",
Expand All @@ -71,8 +76,8 @@ ResponseEntity<List<MemberActionItemResponse>> memberActionItem(@MemberId Long c
)
}
)
ResponseEntity<SpaceActionItemResponse> teamActionItem(@MemberId Long memberId,
@PathVariable Long spaceId);
ResponseEntity<GetSpaceActionItemResponse> spaceRecentActionItem(@MemberId Long memberId,
@PathVariable Long spaceId);

@Operation(summary = "액션 아이템 삭제", method = "DELETE", description = """
액션 아이템을 삭제합니다.
Expand All @@ -81,5 +86,5 @@ ResponseEntity<SpaceActionItemResponse> teamActionItem(@MemberId Long memberId,
@ApiResponse(responseCode = "200")
}
)
ResponseEntity<DeleteActionItemResponse> deleteActionItem(@MemberId Long memberId, @PathVariable("actionItemId") Long actionItemId);
ResponseEntity<Void> deleteActionItem(@MemberId Long memberId, @PathVariable("actionItemId") Long actionItemId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@
import lombok.extern.slf4j.Slf4j;
import org.layer.common.annotation.MemberId;
import org.layer.domain.actionItem.controller.dto.CreateActionItemRequest;
import org.layer.domain.actionItem.controller.dto.CreateActionItemResponse;
import org.layer.domain.actionItem.controller.dto.DeleteActionItemResponse;
import org.layer.domain.actionItem.controller.dto.MemberActionItemResponse;
import org.layer.domain.actionItem.controller.dto.SpaceActionItemResponse;
import org.layer.domain.actionItem.controller.dto.GetSpaceActionItemResponse;
import org.layer.domain.actionItem.controller.dto.GetSpaceRetrospectActionItemResponse;
import org.layer.domain.actionItem.service.ActionItemService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/action-item")
Expand All @@ -26,39 +23,45 @@ public class ActionItemController implements ActionItemApi {
@Override
@PostMapping("/create")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<CreateActionItemResponse> createActionItem(@MemberId Long memberId,
@Validated @RequestBody CreateActionItemRequest createActionItemRequest) {
CreateActionItemResponse actionItem = actionItemService.createActionItem(memberId,
public ResponseEntity<Void> createActionItem(@MemberId Long memberId,
@Validated @RequestBody CreateActionItemRequest createActionItemRequest) {
actionItemService.createActionItem(memberId,
createActionItemRequest.retrospectId(),
createActionItemRequest.content());

return new ResponseEntity<>(actionItem, HttpStatus.CREATED);
return new ResponseEntity<>(null, HttpStatus.CREATED);
}

@Override
@GetMapping("/member/{memberId}")
@GetMapping("/member")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<List<MemberActionItemResponse>> memberActionItem(@MemberId Long currentMemberId, @PathVariable("memberId") Long memberId) {
List<MemberActionItemResponse> memberActionItemList = actionItemService.getMemberActionItemList(currentMemberId, memberId);

return new ResponseEntity<>(memberActionItemList, HttpStatus.OK);
public ResponseEntity<MemberActionItemResponse> memberActionItem(@MemberId Long currentMemberId) {
MemberActionItemResponse memberActionItems = actionItemService.getMemberActionItemList(currentMemberId);
return new ResponseEntity<>(memberActionItems, HttpStatus.OK);
}

@Override
@GetMapping("/space/{spaceId}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<SpaceActionItemResponse> teamActionItem(@MemberId Long memberId, @PathVariable("spaceId") Long spaceId) {
SpaceActionItemResponse teamActionItem = actionItemService.getSpaceActionItemList(memberId, spaceId);
public ResponseEntity<GetSpaceRetrospectActionItemResponse> teamActionItem(@MemberId Long memberId, @PathVariable(name = "spaceId") Long spaceId) {
GetSpaceRetrospectActionItemResponse teamActionItem = actionItemService.getSpaceActionItemList(memberId, spaceId);

return new ResponseEntity<>(teamActionItem, HttpStatus.OK);
}

@Override
@GetMapping("/space/{spaceId}/recent")
public ResponseEntity<GetSpaceActionItemResponse> spaceRecentActionItem(@MemberId Long memberId, @PathVariable(name = "spaceId") Long spaceId) {
GetSpaceActionItemResponse spaceRecentActionItems = actionItemService.getSpaceRecentActionItems(memberId, spaceId);

return new ResponseEntity<>(spaceRecentActionItems, HttpStatus.OK);
}

@Override
@DeleteMapping("/{actionItemId}")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<DeleteActionItemResponse> deleteActionItem(@MemberId Long memberId, @PathVariable("actionItemId") Long actionItemId) {
DeleteActionItemResponse deleteActionItemResponse = actionItemService.deleteActionItem(memberId, actionItemId);

return new ResponseEntity<>(deleteActionItemResponse, HttpStatus.OK);
public ResponseEntity<Void> deleteActionItem(@MemberId Long memberId, @PathVariable("actionItemId") Long actionItemId) {
actionItemService.deleteActionItem(memberId, actionItemId);
return new ResponseEntity<>(null, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.layer.domain.actionItem.controller.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.actionItem.entity.ActionItem;

@Builder
public record ActionItemResponse(@NotNull
@Schema(description = "실행 목표 ID", examples = {"1", "2"})
Long actionItemId,
@NotNull
@Schema(description = "실행 목표 내용", examples = {"긴 회의 시간 줄이기", "회의 후 내용 꼭 기록해두기"})
String content) {
public static ActionItemResponse of(ActionItem actionItem) {
return ActionItemResponse.builder()
.actionItemId(actionItem.getId())
.content(actionItem.getContent())
.build();
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.layer.domain.actionItem.controller.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.actionItem.entity.ActionItem;
import org.layer.domain.retrospect.entity.Retrospect;
import org.layer.domain.space.entity.Space;

import java.util.List;

@Builder
public record GetSpaceActionItemResponse(@NotNull
@Schema(description = "액션 아이템이 속한 스페이스 ID")
Long spaceId,
@NotNull
@Schema(description = "액션 아이템이 속한 스페이스 이름")
String spaceName,
@NotNull
@Schema(description = "스페이스의 액션아이템 리스트")
List<SpaceActionItemElementResponse> teamActionItemList
) {

public static GetSpaceActionItemResponse of(Space space, Retrospect retrospect, List<ActionItem> spaceActionItemList) {
List<SpaceActionItemElementResponse> actionItemElements = spaceActionItemList.stream()
.map(a -> SpaceActionItemElementResponse.of(a, retrospect))
.toList();

return GetSpaceActionItemResponse.builder()
.spaceId(space.getId())
.spaceName(space.getName())
.teamActionItemList(actionItemElements)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.layer.domain.actionItem.controller.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.space.entity.Space;

import java.util.List;

@Builder
public record GetSpaceRetrospectActionItemResponse(@NotNull
@Schema(description = "액션 아이템이 속한 스페이스 ID")
Long spaceId,
@NotNull
@Schema(description = "액션 아이템이 속한 스페이스 이름")
String spaceName,
@NotNull
@Schema(description = "스페이스의 액션아이템 리스트")
List<RetrospectActionItemResponse> teamActionItemList
) {

public static GetSpaceRetrospectActionItemResponse of(Space space, List<RetrospectActionItemResponse> actionItemList) {
return GetSpaceRetrospectActionItemResponse.builder()
.spaceId(space.getId())
.spaceName(space.getName())
.teamActionItemList(actionItemList)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.layer.domain.actionItem.controller.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.actionItem.entity.ActionItem;
import org.layer.domain.actionItem.enums.ActionItemStatus;
import org.layer.domain.retrospect.entity.Retrospect;
import org.layer.domain.space.entity.Space;

@Builder
public record MemberActionItemElementResponse(
@NotNull
@Schema(description = "실행 목표가 속한 스페이스 ID")
Long spaceId,
@NotNull
@Schema(description = "실행 목표가 속한 스페이스 이름")
String spaceName,
@NotNull
@Schema(description = "실행 목표가 속한 회고 ID")
Long retrospectId,
@NotNull
@Schema(description = "실행 목표가 속한 회고 이름")
String retrospectTitle,
@NotNull
@Schema(description = "실행 목표 ID", examples = {"1", "2"})
Long actionItemId,
@NotNull
@Schema(description = "실행 목표 내용", examples = {"긴 회의 시간 줄이기", "회의 후 내용 꼭 기록해두기"})
String content,
@NotNull
@Schema(description = "핀 여부", examples = {"Y", "N"})
String isPinned,
@NotNull
@Schema(description = "실행 목표 상태", examples = {"PROCEEDING", "BEFORE_START", "DONE"})
ActionItemStatus actionItemStatus
) {

public static MemberActionItemElementResponse of(Space space, Retrospect retrospect, ActionItem actionItem) {
return MemberActionItemElementResponse.builder()
.spaceId(space.getId())
.spaceName(space.getName())
.retrospectId(retrospect.getId())
.retrospectTitle(retrospect.getTitle())
.actionItemId(actionItem.getId())
.content(actionItem.getContent())
.isPinned(actionItem.getIsPinned() ? "Y" : "N")
.actionItemStatus(actionItem.getActionItemStatus())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,9 @@
package org.layer.domain.actionItem.controller.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import org.layer.domain.actionItem.entity.ActionItem;

@Builder
@Schema(description = "특정 회원이 작성한 액션 아이템")
public record MemberActionItemResponse (@NotNull
@Schema(description = "액션아이템 ID")
Long actionItemId,
@NotNull
@Schema(description = "액션아이템 내용")
String actionItemContent,
@NotNull
@Schema(description = "액션 아이템이 속해 있는 스페이스 ID")
Long spaceId,
@NotNull
@Schema(description = "액션 아이템이 속해 있는 스페이스 이름")
String spaceName,
@NotNull
@Schema(description = "액션 아이템과 매핑되는 회고 ID")
Long retrospectId,
@NotNull
@Schema(description = "액션 아이템과 매핑되는 회고 이름")
String retrospectName,
@NotNull
@Schema(description = "팀 스페이스의 액션 아이템인지, 개인 스페이스의 액션 아이템인지")
Boolean isTeam){
import java.util.List;

public static MemberActionItemResponse toResponse(ActionItem actionItem, String spaceName, String retrospectName, boolean isTeam) {
return MemberActionItemResponse.builder()
.actionItemId(actionItem.getId())
.actionItemContent(actionItem.getContent())
.spaceId(actionItem.getSpaceId())
.spaceName(spaceName)
.retrospectId(actionItem.getRetrospectId())
.retrospectName(retrospectName)
.isTeam(isTeam)
.build();
}
@Builder
public record MemberActionItemResponse(List<MemberActionItemElementResponse> actionItemResponse) {
}
Loading

0 comments on commit 2fc3927

Please sign in to comment.