Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package clap.server.adapter.inbound.web.admin;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
import clap.server.application.port.inbound.label.FindLabelListUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Tag(name = "05. Admin")
@WebAdapter
@RequiredArgsConstructor
@RequestMapping("/api/managements/label")
public class FindLabelAdminController {

private final FindLabelListUsecase findLabelListUsecase;

@Operation(summary = "구분 목록 조회 API")
@Secured({"ROLE_ADMIN"})
@GetMapping
public ResponseEntity<List<FindLabelListResponse>> findLabelList(
@AuthenticationPrincipal SecurityUserDetails userInfo) {
return ResponseEntity.ok(findLabelListUsecase.findLabelListAdmin(userInfo.getUserId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package clap.server.adapter.inbound.web.dto.label;

import clap.server.adapter.outbound.persistense.entity.task.constant.LabelColor;

public record FindLabelListResponse(
Long labelId,
String labelName,
LabelColor labelColor
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package clap.server.adapter.inbound.web.dto.notification;

public record CountNotificationResponse(
Long memberId,
Integer count
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package clap.server.adapter.inbound.web.dto.task;

public record UpdateTaskLabelRequest(
Long labelId
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package clap.server.adapter.inbound.web.label;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
import clap.server.application.port.inbound.label.FindLabelListUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
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;

import java.util.List;

@Tag(name = "02. Task[검토자]")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/labels")
public class FindLabelController {

private final FindLabelListUsecase findLabelListUsecase;

@Operation(summary = "구분 목록 조회 API")
@Parameters({
@Parameter(name = "page", description = "조회할 목록 페이지 번호(0부터 시작)", example = "0", required = false),
@Parameter(name = "size", description = "조회할 목록 페이지 당 개수", example = "5", required = false)
})
@Secured({"ROLE_MANAGER"})
@GetMapping
public ResponseEntity<SliceResponse<FindLabelListResponse>> findLabelList(
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "5") int size) {
Pageable pageable = PageRequest.of(page, size);
return ResponseEntity.ok(findLabelListUsecase.findLabelList(userInfo.getUserId(), pageable));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.common.SliceResponse;
import clap.server.adapter.inbound.web.dto.notification.CountNotificationResponse;
import clap.server.adapter.inbound.web.dto.notification.FindNotificationListResponse;
import clap.server.application.port.inbound.notification.CountNotificationUseCase;
import clap.server.application.port.inbound.notification.FindNotificationListUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -27,6 +29,7 @@
public class FindNotificationController {

private final FindNotificationListUsecase findNotificationListUsecase;
private final CountNotificationUseCase countNotificationUseCase;

@Operation(summary = "알림 목록 조회 API")
@Parameters({
Expand All @@ -41,4 +44,11 @@ public ResponseEntity<SliceResponse<FindNotificationListResponse>> findNotificat
Pageable pageable = PageRequest.of(page, size);
return ResponseEntity.ok(findNotificationListUsecase.findNotificationList(securityUserDetails.getUserId(), pageable));
}

@Operation(summary = "미확인 알림 개수 조회 API")
@GetMapping("/count")
public ResponseEntity<CountNotificationResponse> countNotification(
@AuthenticationPrincipal SecurityUserDetails userInfo) {
return ResponseEntity.ok(countNotificationUseCase.countNotification(userInfo.getUserId()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package clap.server.adapter.inbound.web.task;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.task.*;
import clap.server.application.port.inbound.task.ApprovalTaskUsecase;
import clap.server.application.port.inbound.task.UpdateTaskLabelUsecase;
import clap.server.application.port.inbound.task.UpdateTaskProcessorUsecase;
import clap.server.application.port.inbound.task.UpdateTaskStatusUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;


@Tag(name = "02. Task[검토자]")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class ChangeTaskController {

private final UpdateTaskStatusUsecase updateTaskStatusUsecase;
private final UpdateTaskProcessorUsecase updateTaskProcessorUsecase;
private final UpdateTaskLabelUsecase updateTaskLabelUsecase;
private final ApprovalTaskUsecase approvalTaskUsecase;

@Operation(summary = "작업 상태 변경")
@Secured({"ROLE_MANGER"})
@PatchMapping("/state/{taskId}")
public ResponseEntity<UpdateTaskResponse> updateTaskState(
@PathVariable @NotNull Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestBody UpdateTaskStatusRequest updateTaskStatusRequest) {

return ResponseEntity.ok(updateTaskStatusUsecase.updateTaskState(userInfo.getUserId(), taskId, updateTaskStatusRequest));
}

@Operation(summary = "작업 처리자 변경")
@Secured({"ROLE_MANAGER"})
@PatchMapping("/processor/{taskId}")
public ResponseEntity<UpdateTaskResponse> updateTaskProcessor(
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestBody UpdateTaskProcessorRequest updateTaskProcessorRequest) {
return ResponseEntity.ok(updateTaskProcessorUsecase.updateTaskProcessor(taskId, userInfo.getUserId(), updateTaskProcessorRequest));
}

@Operation(summary = "작업 구분 변경")
@Secured({"ROLE_MANAGER"})
@PatchMapping("/label/{taskId}")
public ResponseEntity<UpdateTaskResponse> updateTaskLabel(
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestBody UpdateTaskLabelRequest updateTaskLabelRequest) {
return ResponseEntity.ok(updateTaskLabelUsecase.updateTaskLabel(taskId, userInfo.getUserId(), updateTaskLabelRequest));
}

@Operation(summary = "작업 승인")
@Secured({"ROLE_MANAGER"})
@PostMapping("/approval/{taskId}")
public ResponseEntity<ApprovalTaskResponse> approvalTask(
@RequestBody @Valid ApprovalTaskRequest approvalTaskRequest,
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo){
return ResponseEntity.ok(approvalTaskUsecase.approvalTaskByReviewer(userInfo.getUserId(), taskId, approvalTaskRequest));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.task.*;
import clap.server.adapter.inbound.web.dto.task.UpdateTaskProcessorRequest;
import clap.server.application.port.inbound.task.*;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -29,9 +28,6 @@ public class ManagementTaskController {

private final CreateTaskUsecase createTaskUsecase;
private final UpdateTaskUsecase updateTaskUsecase;
private final UpdateTaskStatusUsecase updateTaskStatusUsecase;
private final UpdateTaskProcessorUsecase updateTaskProcessorUsecase;
private final ApprovalTaskUsecase approvalTaskUsecase;

@Operation(summary = "작업 요청 생성")
@PostMapping(consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
Expand All @@ -54,35 +50,4 @@ public ResponseEntity<UpdateTaskResponse> updateTask(
@AuthenticationPrincipal SecurityUserDetails userInfo){
return ResponseEntity.ok(updateTaskUsecase.updateTask(userInfo.getUserId(), taskId, updateTaskRequest, attachments));
}

@Operation(summary = "작업 상태 변경")
@Secured({"ROLE_MANGER"})
@PatchMapping("/state/{taskId}")
public ResponseEntity<UpdateTaskResponse> updateTaskState(
@PathVariable @NotNull Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestBody UpdateTaskStatusRequest updateTaskStatusRequest) {

return ResponseEntity.ok(updateTaskStatusUsecase.updateTaskState(userInfo.getUserId(), taskId, updateTaskStatusRequest));
}

@Operation(summary = "작업 처리자 변경")
@Secured({"ROLE_MANAGER"})
@PatchMapping("/processor/{taskId}")
public ResponseEntity<UpdateTaskResponse> updateTaskProcessor(
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo,
@RequestBody UpdateTaskProcessorRequest updateTaskProcessorRequest) {
return ResponseEntity.ok(updateTaskProcessorUsecase.updateTaskProcessor(taskId, userInfo.getUserId(), updateTaskProcessorRequest));
}

@Operation(summary = "작업 승인")
@Secured({"ROLE_MANAGER"})
@PostMapping("/approval/{taskId}")
public ResponseEntity<ApprovalTaskResponse> approvalTask(
@RequestBody @Valid ApprovalTaskRequest approvalTaskRequest,
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo){
return ResponseEntity.ok(approvalTaskUsecase.approvalTaskByReviewer(userInfo.getUserId(), taskId, approvalTaskRequest));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
package clap.server.adapter.outbound.persistense;

import clap.server.adapter.inbound.web.dto.common.SliceResponse;
import clap.server.adapter.inbound.web.dto.label.FindLabelListResponse;
import clap.server.adapter.inbound.web.dto.notification.FindNotificationListResponse;
import clap.server.adapter.outbound.persistense.entity.task.LabelEntity;
import clap.server.adapter.outbound.persistense.mapper.LabelPersistenceMapper;
import clap.server.adapter.outbound.persistense.repository.task.LabelRepository;
import clap.server.application.mapper.LabelMapper;
import clap.server.application.mapper.NotificationMapper;
import clap.server.application.port.outbound.task.LoadLabelPort;
import clap.server.common.annotation.architecture.PersistenceAdapter;
import clap.server.domain.model.notification.Notification;
import clap.server.domain.model.task.Label;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@PersistenceAdapter
@RequiredArgsConstructor
Expand All @@ -18,8 +28,27 @@ public class LabelPersistenceAdapter implements LoadLabelPort {
private final LabelPersistenceMapper labelPersistenceMapper;

@Override
public Optional<Label> findById(Long id) {
Optional<LabelEntity> labelEntity = labelRepository.findById(id);
public Optional<Label> findById(Long labelId) {
Optional<LabelEntity> labelEntity = labelRepository.findById(labelId);
return labelEntity.map(labelPersistenceMapper::toDomain);
}

@Override
public List<Label> findLabelList() {
List<LabelEntity> labelEntities = labelRepository.findByIsDeletedFalse();

return labelEntities.stream()
.map(labelPersistenceMapper::toDomain)
.collect(Collectors.toList());
}

@Override
public SliceResponse<FindLabelListResponse> findLabelListBySlice(Pageable pageable) {
Slice<Label> labelList = labelRepository.findByIsDeletedFalse(pageable)
.map(labelPersistenceMapper::toDomain);

return LabelMapper.toSliceOfFindNoticeListResponse(
labelList.map(LabelMapper::toFindLabelListResponse)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public List<Notification> findNotificationsByMemberId(Long memberId) {
.collect(Collectors.toList());
}

@Override
public Integer countNotification(Long memberId) {
return notificationRepository.countByIsReadFalseAndReceiver_MemberId(memberId);
}

@Override
public void save(Notification notification) {
notificationRepository.save(notificationPersistenceMapper.toEntity(notification));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package clap.server.adapter.outbound.persistense.repository.notification;

import clap.server.adapter.outbound.persistense.entity.member.MemberEntity;
import clap.server.adapter.outbound.persistense.entity.notification.NotificationEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
Expand All @@ -15,4 +16,6 @@ public interface NotificationRepository extends JpaRepository<NotificationEntity
Slice<NotificationEntity> findAllByReceiver_MemberIdOrderByCreatedAtDesc(Long receiverId, Pageable pageable);

List<NotificationEntity> findAllByReceiver_MemberId(Long memberId);

Integer countByIsReadFalseAndReceiver_MemberId(Long memberId);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package clap.server.adapter.outbound.persistense.repository.task;

import clap.server.adapter.outbound.persistense.entity.task.LabelEntity;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface LabelRepository extends JpaRepository<LabelEntity, Long> {

List<LabelEntity> findByIsDeletedFalse();

Slice<LabelEntity> findByIsDeletedFalse(Pageable pageable);
}
Loading