Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c53965f
CLAP-324 Rename: response dto에 대한 매퍼들을 response 하위 디렉토리로 이동
joowojr Feb 7, 2025
8e2cda8
CLAP-324 Fix: response dto를 outbound adapter에서 반환하는 부분 수정
joowojr Feb 7, 2025
6981c4b
CLAP-324 Refactor: adapter, application layer의 책임 분리
joowojr Feb 7, 2025
bea0c6d
Merge branch 'develop' into CLAP-324
joowojr Feb 7, 2025
1948e82
CLAP-324 Fix: 불필요한 애너테이션 삭제
joowojr Feb 7, 2025
f78a477
CLAP-324 Fix: git conflict solve 및
joowojr Feb 7, 2025
c3063ca
CLAP-324 Style: 팀 현황 조회 엔드포인트 수정
joowojr Feb 7, 2025
ac14db4
CLAP-324 Style: 엔드포인트 계층 구조에 맞게 수정
joowojr Feb 7, 2025
63053da
Merge remote-tracking branch 'origin/develop' into CLAP-324
joowojr Feb 7, 2025
a48f26c
CLAP-324 Refactor: 팀 현황 조회 request validation 추가
joowojr Feb 7, 2025
dac7e50
CLAP-324 Refactor: 누락된 애너테이션 추가
joowojr Feb 7, 2025
2dfeda7
CLAP-324 통계 서비스 매퍼 수정으로 인한 버그 수정
hyoseong-Choi Feb 7, 2025
dc3944d
CLAP-324 Fix: 작성자만 댓글 수정 삭제 권한이 있도록 수정
joowojr Feb 7, 2025
5b7b8d8
CLAP-324 Feat: 댓글 작성 권한 검증policy 클래스 추가
joowojr Feb 7, 2025
471b179
CLAP-324 Remove: 필요없는 클래스 삭제
joowojr Feb 7, 2025
289a04e
CLAP-324 Style: userId -> memberId 네이밍 수정
joowojr Feb 7, 2025
19a2819
Merge remote-tracking branch 'origin/CLAP-324' into CLAP-324
joowojr Feb 7, 2025
0f2236b
Merge remote-tracking branch 'origin/develop' into CLAP-324
joowojr Feb 7, 2025
e760682
CLAP-324 Fix: git conflict solve
joowojr Feb 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
package clap.server.adapter.inbound.web.dto.task.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import java.util.List;

public record FilterTeamStatusRequest(
@Schema(description = "정렬 기준 (기여도순, 기본)", example = "기여도순")
SortBy sortBy, // Enum 타입으로 수정
@Schema(description = "정렬 기준 (기여도순, 기본)", example = "DEFAULT")
@NotNull
SortBy sortBy,

@Schema(description = "1차 카테고리 ID 목록", example = "[10, 20, 30]")
@NotBlank
List<Long> mainCategoryIds,

@Schema(description = "2차 카테고리 ID 목록", example = "[1, 2, 3]")
List<Long> categoryIds,

@Schema(description = "작업 타이틀 검색", example = "타이틀1")
@NotNull
String taskTitle
) {
public FilterTeamStatusRequest {
// 기본값 설정
sortBy = (sortBy == null) ? SortBy.DEFAULT : sortBy; // 기본값을 DEFAULT로 설정
mainCategoryIds = mainCategoryIds == null ? List.of() : mainCategoryIds;
categoryIds = categoryIds == null ? List.of() : categoryIds;
taskTitle = taskTitle == null ? "" : taskTitle;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,4 @@ public static record LabelInfo(
LabelColor labelColor
) {
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package clap.server.adapter.inbound.web.dto.task.response;

import com.querydsl.core.annotations.QueryProjection;

import java.util.List;

public record TeamTaskResponse(
Expand All @@ -14,8 +12,4 @@ public record TeamTaskResponse(
int totalTaskCount,
List<TeamTaskItemResponse> tasks
) {
@QueryProjection
public TeamTaskResponse {
tasks = (tasks == null) ? List.of() : tasks;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

@Tag(name = "03. Task History", description = "히스토리 및 댓글 관련 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/comments")
public class CommandCommentController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

@Tag(name = "03. Task History")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class FindTaskHistoryController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@

@Tag(name = "03. Task History")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/comments")
@RequestMapping("/api/tasks")
public class PostCommentController {

private final SaveCommentUsecase saveCommentUsecase;
private final SaveCommentAttachmentUsecase saveCommentAttachmentUsecase;
@LogType(LogStatus.COMMENT_ADDED)
@Operation(summary = "댓글 작성")
@Parameter(name = "taskId", description = "댓글 작성할 작업 고유 ID", required = true, in = ParameterIn.PATH)
@PostMapping("/{taskId}")
@PostMapping("/{taskId}/comments")
@Secured({"ROLE_MANAGER", "ROLE_USER"})
public void createComment(
@AuthenticationPrincipal SecurityUserDetails userInfo,
Expand All @@ -43,7 +42,7 @@ public void createComment(

@Operation(summary = "댓글 작성(첨부 파일)")
@Parameter(name = "taskId", description = "댓글 작성할 작업 고유 ID", required = true, in = ParameterIn.PATH)
@PostMapping(value = "/attachment/{taskId}", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
@PostMapping(value = "/{taskId}/comments/attachment", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
@Secured({"ROLE_MANAGER", "ROLE_USER"})
public void createAttachmentComment(
@AuthenticationPrincipal SecurityUserDetails userInfo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

@Tag(name = "02. Task [조회]", description = "담당자 및 관리자 공통으로 사용")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/labels")
public class FindLabelController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

@Tag(name = "05. Admin [로깅]")
@WebAdapter
@RestController
@RequestMapping("/api/managements/logs")
@RequiredArgsConstructor
public class LogController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

@Tag(name = "04. Notification")
@WebAdapter
@RestController
@RequestMapping("/api/notifications")
@RequiredArgsConstructor
public class FindNotificationController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

@Tag(name = "04. Notification")
@WebAdapter
@RestController
@RequestMapping("/api/notifications")
@RequiredArgsConstructor
public class ManagementNotificationController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

@Tag(name = "SSE 관리 - 회원 등록(최초 접속시)")
@WebAdapter
@RestController
@RequestMapping("/api/sse")
@RequiredArgsConstructor
public class SubscribeEmitterController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public ResponseEntity<List<StatisticsResponse>> aggregateTaskStatistics(@Request
return switch (statisticsType) {
case REQUEST_BY_PERIOD ->
ResponseEntity.ok(findTaskProcessUsecase.aggregatePeriodTaskRequest(periodType.getType()));
case PROCESS_BY_PERIOD -> ResponseEntity.ok(findTaskProcessUsecase
.aggregatePeriodTaskProcess(periodType.getType()));
case PROCESS_BY_PERIOD ->
ResponseEntity.ok(findTaskProcessUsecase.aggregatePeriodTaskProcess(periodType.getType()));
case REQUEST_BY_CATEGORY ->
ResponseEntity.ok(findTaskProcessUsecase.aggregateCategoryTaskRequest(periodType.getType()));
case PROCESS_BY_MANAGER -> ResponseEntity.ok(findTaskProcessUsecase
.aggregateManagerTaskProcess(periodType.getType()));
case PROCESS_BY_MANAGER ->
ResponseEntity.ok(findTaskProcessUsecase.aggregateManagerTaskProcess(periodType.getType()));
default -> throw new StatisticsException(STATISTICS_BAD_REQUEST);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@

@Tag(name = "02. Task [검토자]")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class ChangeTaskController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

@Tag(name = "02. Task [조회]", description = "작업 조회 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class FindApprovalTaskFormController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

@Tag(name = "02. Task [조회]", description = "작업 조회 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class FindTaskController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@

@Tag(name = "02. Task [생성/수정]", description = "작업 생성/수정 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class ManagementTaskController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

@Tag(name = "02. Task [담당자]")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/task-board")
public class TaskBoardController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import clap.server.adapter.inbound.web.dto.task.request.FilterTeamStatusRequest;
import clap.server.adapter.inbound.web.dto.task.response.TeamStatusResponse;
import clap.server.application.service.task.TeamStatusService;
import clap.server.application.port.inbound.task.FilterTeamStatusUsecase;
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 lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
Expand All @@ -20,13 +21,13 @@
@RequiredArgsConstructor
@WebAdapter
public class TeamStatusController {
private final FilterTeamStatusUsecase filterTeamStatusUsecase;

private final TeamStatusService teamStatusService;
@Operation(summary = "팀 현황 필터링 조회 API")
@GetMapping("/filter")
@Operation(summary = "팀 현황 조회 API")
@GetMapping()
@Secured("ROLE_MANAGER")
public ResponseEntity<TeamStatusResponse> filterTeamStatus(@ModelAttribute FilterTeamStatusRequest filter) {
TeamStatusResponse response = teamStatusService.filterTeamStatus(filter);
public ResponseEntity<TeamStatusResponse> filterTeamStatus(@ModelAttribute @Valid FilterTeamStatusRequest filter) {
TeamStatusResponse response = filterTeamStatusUsecase.filterTeamStatus(filter);
return ResponseEntity.ok(response != null ? response : new TeamStatusResponse(List.of(), 0, 0, 0));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

@Tag(name = "02. Task [거부 & 종료]")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class TerminateTaskController {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package clap.server.adapter.outbound.persistense;

import clap.server.adapter.inbound.web.dto.common.SliceResponse;
import clap.server.adapter.inbound.web.dto.notification.response.FindNotificationListResponse;
import clap.server.adapter.outbound.persistense.mapper.NotificationPersistenceMapper;
import clap.server.adapter.outbound.persistense.repository.notification.NotificationRepository;
import clap.server.application.mapper.NotificationMapper;
import clap.server.application.port.outbound.notification.CommandNotificationPort;
import clap.server.application.port.outbound.notification.LoadNotificationPort;
import clap.server.common.annotation.architecture.PersistenceAdapter;
Expand Down Expand Up @@ -32,14 +29,10 @@ public Optional<Notification> findById(Long notificationId) {
}

@Override
public SliceResponse<FindNotificationListResponse> findAllByReceiverId(Long receiverId, Pageable pageable) {
Slice<Notification> notificationList = notificationRepository
public Slice<Notification> findAllByReceiverId(Long receiverId, Pageable pageable) {
return notificationRepository
.findAllByReceiver_MemberIdOrderByCreatedAtDesc(receiverId, pageable)
.map(notificationPersistenceMapper::toDomain);

return NotificationMapper.toSliceOfFindNoticeListResponse(
notificationList.map(NotificationMapper::toFindNoticeListResponse)
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ public Optional<Task> findNextOrderTaskByTaskIdAndStatus(Long processorId, TaskS

@Override
public List<Task> findTaskBoardByFilter(Long processorId, List<TaskStatus> statuses, LocalDateTime fromDate, FilterTaskBoardRequest request) {
return taskRepository.findTasksByFilter(processorId, statuses, fromDate, request)
return taskRepository.findTasksByFilter(processorId, statuses, fromDate, request)
.stream()
.map(taskPersistenceMapper::toDomain).toList();
}

@Override
public List<TeamTaskResponse> findTeamStatus(Long memberId, FilterTeamStatusRequest filter) {
return taskRepository.findTeamStatus(memberId, filter);
public List<Task> findTeamStatus(Long memberId, FilterTeamStatusRequest filter) {
return taskRepository.findTeamStatus(memberId, filter).stream()
.map(taskPersistenceMapper::toDomain).toList();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public interface TaskCustomRepository {

Page<TaskEntity> findTasksRequestedByUser(Long requesterId, Pageable pageable, FilterTaskListRequest findTaskListRequest);
List<TeamTaskResponse> findTeamStatus(Long memberId, FilterTeamStatusRequest filter);
List<TaskEntity> findTeamStatus(Long memberId, FilterTeamStatusRequest filter);
Page<TaskEntity> findPendingApprovalTasks(Pageable pageable, FilterTaskListRequest findTaskListRequest);
Page<TaskEntity> findAllTasks(Pageable pageable, FilterTaskListRequest findTaskListRequest);
List<TaskEntity> findTasksByFilter(Long processorId, List<TaskStatus> statuses, LocalDateTime localDateTime, FilterTaskBoardRequest request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import clap.server.adapter.inbound.web.dto.task.response.TeamTaskResponse;
import clap.server.adapter.outbound.persistense.entity.task.TaskEntity;
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;
import clap.server.domain.model.task.Task;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.DateTimePath;
Expand Down Expand Up @@ -58,8 +59,15 @@ public Page<TaskEntity> findTasksAssignedByManager(Long processorId, Pageable pa
}

@Override
public List<TeamTaskResponse> findTeamStatus(Long memberId, FilterTeamStatusRequest filter) {
// filter가 null인 경우에도 기본적으로 모든 데이터를 조회하도록 처리
public List<TaskEntity> findTeamStatus(Long memberId, FilterTeamStatusRequest filter) {
BooleanBuilder builder = createFilterBuilder(memberId, filter);
return queryFactory
.selectFrom(taskEntity)
.where(builder)
.fetch();
}

private BooleanBuilder createFilterBuilder(Long memberId, FilterTeamStatusRequest filter) {
BooleanBuilder builder = new BooleanBuilder();

// 필터가 null인 경우, 기본적으로 모든 데이터 조회
Expand Down Expand Up @@ -87,74 +95,7 @@ public List<TeamTaskResponse> findTeamStatus(Long memberId, FilterTeamStatusRequ
builder.and(taskEntity.category.categoryId.in(filter.categoryIds()));
}
}

// 정렬 조건 적용
SortBy sortBy = (filter != null && filter.sortBy() != null) ? filter.sortBy() : SortBy.DEFAULT;

assert filter != null;
// 쿼리 실행
List<TaskEntity> taskEntities = queryFactory
.selectFrom(taskEntity)
.where(builder)
.fetch();

// null 또는 빈 리스트 처리
if (taskEntities == null || taskEntities.isEmpty()) {
return List.of(); // 빈 리스트 반환
}

List<TeamTaskResponse> members = taskEntities.stream()
.collect(Collectors.groupingBy(t -> t.getProcessor().getMemberId(), LinkedHashMap::new, Collectors.toList()))
.entrySet().stream()
.map(entry -> {
List<TeamTaskItemResponse> taskResponses = entry.getValue().stream()
.map(taskEntity -> new TeamTaskItemResponse(
taskEntity.getTaskId(),
taskEntity.getTaskCode(),
taskEntity.getTitle(),
taskEntity.getCategory().getMainCategory().getName(),
taskEntity.getCategory().getName(),
taskEntity.getLabel() != null ?
new TeamTaskItemResponse.LabelInfo(
taskEntity.getLabel().getLabelName(),
taskEntity.getLabel().getLabelColor()
) : null,
taskEntity.getRequester().getNickname(),
taskEntity.getRequester().getImageUrl(),
taskEntity.getRequester().getDepartment().getName(),
taskEntity.getProcessorOrder(),
taskEntity.getTaskStatus(),
taskEntity.getCreatedAt()
)).collect(Collectors.toList());

int inProgressTaskCount = (int) entry.getValue().stream().filter(t -> t.getTaskStatus() == TaskStatus.IN_PROGRESS).count();
int inReviewingTaskCount = (int) entry.getValue().stream().filter(t -> t.getTaskStatus() == TaskStatus.IN_REVIEWING).count();
int totalTaskCount = inProgressTaskCount + inReviewingTaskCount;

return new TeamTaskResponse(
entry.getKey(),
entry.getValue().get(0).getProcessor().getNickname(),
entry.getValue().get(0).getProcessor().getImageUrl(),
entry.getValue().get(0).getProcessor().getDepartment().getName(),
(int) entry.getValue().stream().filter(t -> t.getTaskStatus() == TaskStatus.IN_PROGRESS).count(),
(int) entry.getValue().stream().filter(t -> t.getTaskStatus() == TaskStatus.IN_REVIEWING).count(),
entry.getValue().size(),
taskResponses
);
}).collect(Collectors.toList());

// 기여도순 (진행 중 + 검토 중 작업 개수 합 기준 내림차순)
if (sortBy.equals(CONTRIBUTE)) members.sort((a, b) -> b.totalTaskCount() - a.totalTaskCount());
// 기본순 (닉네임 오름차순)
else members.sort(Comparator.comparing(TeamTaskResponse::nickname));

return members;
}



private boolean isValidTitle(FilterTeamStatusRequest filter) {
return filter.taskTitle() != null && !filter.taskTitle().isEmpty();
return builder;
}

@Override
Expand Down
Loading