Skip to content

Commit 001eb7b

Browse files
authored
Merge pull request #156 from TaskFlow-CLAP/CLAP-165
CLAP-165 구분 목록 조회 API 구현
2 parents 414b6ad + f7b8d10 commit 001eb7b

File tree

10 files changed

+307
-3
lines changed

10 files changed

+307
-3
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package clap.server.adapter.inbound.web.admin;
2+
3+
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
5+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
6+
import clap.server.application.port.inbound.label.FindLabelListUsecase;
7+
import clap.server.common.annotation.architecture.WebAdapter;
8+
import io.swagger.v3.oas.annotations.Operation;
9+
import io.swagger.v3.oas.annotations.tags.Tag;
10+
import lombok.RequiredArgsConstructor;
11+
import org.springframework.http.ResponseEntity;
12+
import org.springframework.security.access.annotation.Secured;
13+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
14+
import org.springframework.web.bind.annotation.GetMapping;
15+
import org.springframework.web.bind.annotation.RequestMapping;
16+
17+
import java.util.List;
18+
19+
@Tag(name = "05. Admin")
20+
@WebAdapter
21+
@RequiredArgsConstructor
22+
@RequestMapping("/api/managements/label")
23+
public class FindLabelAdminController {
24+
25+
private final FindLabelListUsecase findLabelListUsecase;
26+
27+
@Operation(summary = "구분 목록 조회 API")
28+
@Secured({"ROLE_ADMIN"})
29+
@GetMapping
30+
public ResponseEntity<List<FindLabelListResponse>> findLabelList(
31+
@AuthenticationPrincipal SecurityUserDetails userInfo) {
32+
return ResponseEntity.ok(findLabelListUsecase.findLabelListAdmin(userInfo.getUserId()));
33+
}
34+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package clap.server.adapter.inbound.web.dto.label;
2+
3+
import clap.server.adapter.outbound.persistense.entity.task.constant.LabelColor;
4+
5+
public record FindLabelListResponse(
6+
Long labelId,
7+
String labelName,
8+
LabelColor labelColor
9+
) {
10+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package clap.server.adapter.inbound.web.label;
2+
3+
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
5+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
6+
import clap.server.application.port.inbound.label.FindLabelListUsecase;
7+
import clap.server.common.annotation.architecture.WebAdapter;
8+
import io.swagger.v3.oas.annotations.Operation;
9+
import io.swagger.v3.oas.annotations.Parameter;
10+
import io.swagger.v3.oas.annotations.Parameters;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.data.domain.PageRequest;
14+
import org.springframework.data.domain.Pageable;
15+
import org.springframework.http.ResponseEntity;
16+
import org.springframework.security.access.annotation.Secured;
17+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
18+
import org.springframework.web.bind.annotation.GetMapping;
19+
import org.springframework.web.bind.annotation.RequestMapping;
20+
import org.springframework.web.bind.annotation.RequestParam;
21+
import org.springframework.web.bind.annotation.RestController;
22+
23+
import java.util.List;
24+
25+
@Tag(name = "02. Task[검토자]")
26+
@WebAdapter
27+
@RestController
28+
@RequiredArgsConstructor
29+
@RequestMapping("/api/labels")
30+
public class FindLabelController {
31+
32+
private final FindLabelListUsecase findLabelListUsecase;
33+
34+
@Operation(summary = "구분 목록 조회 API")
35+
@Parameters({
36+
@Parameter(name = "page", description = "조회할 목록 페이지 번호(0부터 시작)", example = "0", required = false),
37+
@Parameter(name = "size", description = "조회할 목록 페이지 당 개수", example = "5", required = false)
38+
})
39+
@Secured({"ROLE_MANAGER"})
40+
@GetMapping
41+
public ResponseEntity<SliceResponse<FindLabelListResponse>> findLabelList(
42+
@AuthenticationPrincipal SecurityUserDetails userInfo,
43+
@RequestParam(defaultValue = "0") int page,
44+
@RequestParam(defaultValue = "5") int size) {
45+
Pageable pageable = PageRequest.of(page, size);
46+
return ResponseEntity.ok(findLabelListUsecase.findLabelList(userInfo.getUserId(), pageable));
47+
}
48+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package clap.server.adapter.inbound.web.task;
2+
3+
import clap.server.adapter.inbound.security.SecurityUserDetails;
4+
import clap.server.adapter.inbound.web.dto.task.*;
5+
import clap.server.application.port.inbound.task.ApprovalTaskUsecase;
6+
import clap.server.application.port.inbound.task.UpdateTaskLabelUsecase;
7+
import clap.server.application.port.inbound.task.UpdateTaskProcessorUsecase;
8+
import clap.server.application.port.inbound.task.UpdateTaskStatusUsecase;
9+
import clap.server.common.annotation.architecture.WebAdapter;
10+
import io.swagger.v3.oas.annotations.Operation;
11+
import io.swagger.v3.oas.annotations.tags.Tag;
12+
import jakarta.validation.Valid;
13+
import jakarta.validation.constraints.NotNull;
14+
import lombok.RequiredArgsConstructor;
15+
import org.springframework.http.ResponseEntity;
16+
import org.springframework.security.access.annotation.Secured;
17+
import org.springframework.security.core.annotation.AuthenticationPrincipal;
18+
import org.springframework.web.bind.annotation.*;
19+
20+
21+
@Tag(name = "02. Task[검토자]")
22+
@WebAdapter
23+
@RestController
24+
@RequiredArgsConstructor
25+
@RequestMapping("/api/tasks")
26+
public class ChangeTaskController {
27+
28+
private final UpdateTaskStatusUsecase updateTaskStatusUsecase;
29+
private final UpdateTaskProcessorUsecase updateTaskProcessorUsecase;
30+
private final UpdateTaskLabelUsecase updateTaskLabelUsecase;
31+
private final ApprovalTaskUsecase approvalTaskUsecase;
32+
33+
@Operation(summary = "작업 상태 변경")
34+
@Secured({"ROLE_MANGER"})
35+
@PatchMapping("/state/{taskId}")
36+
public ResponseEntity<UpdateTaskResponse> updateTaskState(
37+
@PathVariable @NotNull Long taskId,
38+
@AuthenticationPrincipal SecurityUserDetails userInfo,
39+
@RequestBody UpdateTaskStatusRequest updateTaskStatusRequest) {
40+
41+
return ResponseEntity.ok(updateTaskStatusUsecase.updateTaskState(userInfo.getUserId(), taskId, updateTaskStatusRequest));
42+
}
43+
44+
@Operation(summary = "작업 처리자 변경")
45+
@Secured({"ROLE_MANAGER"})
46+
@PatchMapping("/processor/{taskId}")
47+
public ResponseEntity<UpdateTaskResponse> updateTaskProcessor(
48+
@PathVariable Long taskId,
49+
@AuthenticationPrincipal SecurityUserDetails userInfo,
50+
@RequestBody UpdateTaskProcessorRequest updateTaskProcessorRequest) {
51+
return ResponseEntity.ok(updateTaskProcessorUsecase.updateTaskProcessor(taskId, userInfo.getUserId(), updateTaskProcessorRequest));
52+
}
53+
54+
@Operation(summary = "작업 구분 변경")
55+
@Secured({"ROLE_MANAGER"})
56+
@PatchMapping("/label/{taskId}")
57+
public ResponseEntity<UpdateTaskResponse> updateTaskLabel(
58+
@PathVariable Long taskId,
59+
@AuthenticationPrincipal SecurityUserDetails userInfo,
60+
@RequestBody UpdateTaskLabelRequest updateTaskLabelRequest) {
61+
return ResponseEntity.ok(updateTaskLabelUsecase.updateTaskLabel(taskId, userInfo.getUserId(), updateTaskLabelRequest));
62+
}
63+
64+
@Operation(summary = "작업 승인")
65+
@Secured({"ROLE_MANAGER"})
66+
@PostMapping("/approval/{taskId}")
67+
public ResponseEntity<ApprovalTaskResponse> approvalTask(
68+
@RequestBody @Valid ApprovalTaskRequest approvalTaskRequest,
69+
@PathVariable Long taskId,
70+
@AuthenticationPrincipal SecurityUserDetails userInfo){
71+
return ResponseEntity.ok(approvalTaskUsecase.approvalTaskByReviewer(userInfo.getUserId(), taskId, approvalTaskRequest));
72+
}
73+
}
Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
package clap.server.adapter.outbound.persistense;
22

3+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
4+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
5+
import clap.server.adapter.inbound.web.dto.notification.FindNotificationListResponse;
36
import clap.server.adapter.outbound.persistense.entity.task.LabelEntity;
47
import clap.server.adapter.outbound.persistense.mapper.LabelPersistenceMapper;
58
import clap.server.adapter.outbound.persistense.repository.task.LabelRepository;
9+
import clap.server.application.mapper.LabelMapper;
10+
import clap.server.application.mapper.NotificationMapper;
611
import clap.server.application.port.outbound.task.LoadLabelPort;
712
import clap.server.common.annotation.architecture.PersistenceAdapter;
13+
import clap.server.domain.model.notification.Notification;
814
import clap.server.domain.model.task.Label;
915
import lombok.RequiredArgsConstructor;
16+
import org.springframework.data.domain.Pageable;
17+
import org.springframework.data.domain.Slice;
1018

19+
import java.util.List;
1120
import java.util.Optional;
21+
import java.util.stream.Collectors;
1222

1323
@PersistenceAdapter
1424
@RequiredArgsConstructor
@@ -18,8 +28,27 @@ public class LabelPersistenceAdapter implements LoadLabelPort {
1828
private final LabelPersistenceMapper labelPersistenceMapper;
1929

2030
@Override
21-
public Optional<Label> findById(Long id) {
22-
Optional<LabelEntity> labelEntity = labelRepository.findById(id);
31+
public Optional<Label> findById(Long labelId) {
32+
Optional<LabelEntity> labelEntity = labelRepository.findById(labelId);
2333
return labelEntity.map(labelPersistenceMapper::toDomain);
2434
}
35+
36+
@Override
37+
public List<Label> findLabelList() {
38+
List<LabelEntity> labelEntities = labelRepository.findByIsDeletedFalse();
39+
40+
return labelEntities.stream()
41+
.map(labelPersistenceMapper::toDomain)
42+
.collect(Collectors.toList());
43+
}
44+
45+
@Override
46+
public SliceResponse<FindLabelListResponse> findLabelListBySlice(Pageable pageable) {
47+
Slice<Label> labelList = labelRepository.findByIsDeletedFalse(pageable)
48+
.map(labelPersistenceMapper::toDomain);
49+
50+
return LabelMapper.toSliceOfFindNoticeListResponse(
51+
labelList.map(LabelMapper::toFindLabelListResponse)
52+
);
53+
}
2554
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package clap.server.adapter.outbound.persistense.repository.task;
22

33
import clap.server.adapter.outbound.persistense.entity.task.LabelEntity;
4+
import org.springframework.data.domain.Pageable;
5+
import org.springframework.data.domain.Slice;
46
import org.springframework.data.jpa.repository.JpaRepository;
57
import org.springframework.stereotype.Repository;
68

9+
import java.util.List;
10+
711
@Repository
812
public interface LabelRepository extends JpaRepository<LabelEntity, Long> {
13+
14+
List<LabelEntity> findByIsDeletedFalse();
15+
16+
Slice<LabelEntity> findByIsDeletedFalse(Pageable pageable);
917
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package clap.server.application.mapper;
2+
3+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
4+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
5+
import clap.server.adapter.inbound.web.dto.notification.FindNotificationListResponse;
6+
import clap.server.domain.model.task.Label;
7+
import org.springframework.data.domain.Slice;
8+
9+
public class LabelMapper {
10+
11+
private LabelMapper() {
12+
throw new IllegalArgumentException();
13+
}
14+
15+
public static FindLabelListResponse toFindLabelListResponse(Label label) {
16+
return new FindLabelListResponse(
17+
label.getLabelId(),
18+
label.getLabelName(),
19+
label.getLabelColor()
20+
);
21+
}
22+
23+
public static SliceResponse<FindLabelListResponse> toSliceOfFindNoticeListResponse(Slice<FindLabelListResponse> slice) {
24+
return new SliceResponse<>(
25+
slice.getContent(),
26+
slice.hasNext(),
27+
slice.isFirst(),
28+
slice.isLast()
29+
);
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package clap.server.application.port.inbound.label;
2+
3+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
4+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
5+
import org.springframework.data.domain.Pageable;
6+
7+
import java.util.List;
8+
9+
public interface FindLabelListUsecase {
10+
11+
SliceResponse<FindLabelListResponse> findLabelList(Long userId, Pageable pageable);
12+
List<FindLabelListResponse> findLabelListAdmin(Long userId);
13+
}
Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
package clap.server.application.port.outbound.task;
22

3+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
4+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
35
import clap.server.domain.model.task.Label;
6+
import org.springframework.data.domain.Pageable;
47

8+
import java.util.List;
59
import java.util.Optional;
610

711
public interface LoadLabelPort {
812

9-
Optional<Label> findById(Long id);
13+
Optional<Label> findById(Long labelId);
14+
15+
List<Label> findLabelList();
16+
17+
SliceResponse<FindLabelListResponse> findLabelListBySlice(Pageable pageable);
18+
19+
20+
21+
1022
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package clap.server.application.service.label;
2+
3+
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
4+
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
5+
import clap.server.application.mapper.LabelMapper;
6+
import clap.server.application.port.inbound.domain.MemberService;
7+
import clap.server.application.port.inbound.label.FindLabelListUsecase;
8+
import clap.server.application.port.outbound.task.LoadLabelPort;
9+
import clap.server.common.annotation.architecture.ApplicationService;
10+
import clap.server.domain.model.member.Member;
11+
import clap.server.exception.ApplicationException;
12+
import clap.server.exception.code.MemberErrorCode;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.data.domain.Pageable;
15+
import org.springframework.transaction.annotation.Transactional;
16+
17+
import java.util.List;
18+
19+
@ApplicationService
20+
@RequiredArgsConstructor
21+
@Transactional(readOnly = true)
22+
public class FindLabelListService implements FindLabelListUsecase {
23+
24+
private final LoadLabelPort loadLabelPort;
25+
private final MemberService memberService;
26+
27+
@Override
28+
public SliceResponse<FindLabelListResponse> findLabelList(Long userId, Pageable pageable) {
29+
Member member = memberService.findActiveMember(userId);
30+
31+
// 담당자인데 검토자가 아닌 경우 Error 처리
32+
if (!member.getMemberInfo().isReviewer()) {
33+
throw new ApplicationException(MemberErrorCode.NOT_A_REVIEWER);
34+
}
35+
return loadLabelPort.findLabelListBySlice(pageable);
36+
}
37+
38+
@Override
39+
public List<FindLabelListResponse> findLabelListAdmin(Long userId) {
40+
memberService.findActiveMember(userId);
41+
return loadLabelPort.findLabelList()
42+
.stream()
43+
.map(LabelMapper::toFindLabelListResponse)
44+
.toList();
45+
}
46+
}

0 commit comments

Comments
 (0)